亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Windows Sockets API實現網絡異步通訊

2019-11-17 05:05:17
字體:
來源:轉載
供稿:網友
[文章信息] 作者:信息產業部電子第二十二研究所青島分所郎銳[文章導讀] 本文對如何使用面向連接的流式套接字實現對網卡的編程以及如何實現異步網絡通訊等問題進行了討論與闡述
摘要: 本文對如何使用面向連接的流式套接字實現對網卡的編程以及如何實現異步網絡通訊等問題進行了討論與闡述。 一、 引言 在80年代初,美國加利福尼亞大學伯克利分校的研究人員為TCP/ip網絡通信開發了一個專門用于網絡通訊開發的API。這個API就是Socket接口(套接字)--當今在TCP/IP網絡最為通用的一種API,也是在互聯網上進行應用開發最為通用的一種API。在微軟聯合其它幾家公司共同制定了一套Windows下的網絡編程接口Windows Sockets規范后,由于在其規范中引入了一些異步函數,增加了對網絡事件異步選擇機制,因此更加符合Windows的消息驅動特性,使網絡開發人員可以更加方便的進行高性能網絡通訊程序的設計。本文接下來就針對Windows Sockets API進行面向連接的流式套接字編程以及對異步網絡通訊的編程實現等問題展開討論。 二、 面向連接的流式套接字編程模型的設計 本文在方案選擇上采用了在網絡編程中最常用的一種模型--客戶機/服務器模型。這種客戶/服務器模型是一種非對稱式編程模式。該模式的基本思想是把集中在一起的應用劃分成為功能不同的兩個部分,分別在不同的計算機上運行,通過它們之間的分工合作來實現一個完整的功能。對于這種模式而言其中一部分需要作為服務器,用來響應并為客戶提供固定的服務;另一部分則作為客戶機程序用來向服務器提出請求或要求某種服務。 本文選取了基于TCP/IP的客戶機/服務器模型和面向連接的流式套接字。其通信原理為:服務器端和客戶端都必須建立通信套接字,而且服務器端應先進入監聽狀態,然后客戶端套接字發出連接請求,服務器端收到請求后,建立另一個套接字進行通信,原來負責監聽的套接字仍進行監聽,假如有其它客戶發來連接請求,則再建立一個套接字。默認狀態下最多可同時接收5個客戶的連接請求,并與之建立通信關系。因此本程序的設計流程應當由服務器首先啟動,然后在某一時刻啟動客戶機并使其與服務器建立連接。服務器與客戶機開始都必須調用Windows Sockets API函數socket()建立一個套接字sockets,然后服務器方調用bind()將套接字與一個本地網絡地址捆扎在一起,再調用listen()使套接字處于一種被動的預備接收狀態,同時規定它的請求隊列長度。在此之后服務器就可以通過調用accept()來接收客戶機的連接。 相對于服務器,客戶端的工作就顯得比較簡單了,當客戶端打開套接字之后,便可通過調用connect()和服務器建立連接。連接建立之后,客戶和服務器之間就可以通過連接發送和接收資料。最后資料傳送結束,雙方調用closesocket()關閉套接字來結束這次通訊。整個通訊過程的具體流程框圖可大致用下面的流程圖來表示:

(圖片較大,請拉動滾動條觀看)
面向連接的流式套接字編程流程示意圖 更多文章 更多內容請看Windows操作系統安全集  Windows操作系統安裝  Windows頻道專題,或 三、 軟件設計要點以及異步通訊的實現


  根據前面設計的程序流程,可將程序劃分為兩部分:服務器端和客戶端。而且整個實現過程可以大致用以下幾個非常要害的Windows Sockets API函數將其慣穿下來:

  服務器方:

socket()-> bind()-> listen-> accept()-> recv()/send()-> closesocket()
  客戶機方:

socket()-> connect()-> send()/recv()-> closesocket()
  有鑒于以上幾個函數在整個網絡編程中的重要性,有必要結合程序實例對其做較深入的剖析。服務器端應用程序在使用套接字之前,首先必須擁有一個Socket,系統調用socket()函數向應用程序提供創建套接字的手段。該套接字實際上是在計算機中提供了一個通信埠,可以通過這個埠與任何一個具有套接字接口的計算機通信。應用程序在網絡上傳輸、接收的信息都通過這個套接字接口來實現的。在應用開發中如同使用文件句柄一樣,可以對套接字句柄進行讀寫操作:

sock=socket(AF_INET,SOCK_STREAM,0);
  函數的第一個參數用于指定地址族,在Windows下僅支持AF_INET(TCP/IP地址);第二個參數用于描述套接字的類型,對于流式套接字提供有SOCK_STREAM;最后一個參數指定套接字使用的協議,一般為0。該函數的返回值保存了新套接字的句柄,在程序退出前可以用 closesocket(sock);函數來將其釋放。服務器方一旦獲取了一個新的套接字后應通過bind()將該套接字與本機上的一個端口相關聯:

sockin.sin_family=AF_INET;
sockin.sin_addr.s_addr=0;
sockin.sin_port=htons(USERPORT);
bind(sock,(LPSOCKADDR)&sockin,sizeof(sockin)));

  該函數的第二個參數是一個指向包含有本機IP地址和端口信息的sockaddr_in結構類型的指針,其成員描述了本地端口號和本地主機地址,經過bind()將服務器進程在網絡上標識出來。需要注重的是由于1024以內的埠號都是保留的埠號因此如無非凡需要一般不能將sockin.sin_port的埠號設置為1024以內的值。然后調用listen()函數開始偵聽,再通過accept()調用等待接收連接以完成連接的建立:

//連接請求隊列長度為1,即只答應有一個請求,若有多個請求,
//則出現錯誤,給出錯誤代碼WSAECONNREFUSED。
listen(sock,1);
//開啟線程避免主程序的阻塞
AfxBeginThread(Server,NULL);
……
UINT Server(LPVOID lpVoid)
{
……
int nLen=sizeof(SOCKADDR);
pView-> newskt=accept(pView-> sock,(LPSOCKADDR)& pView-> sockin,(LPINT)& nLen);
……
WSAAsyncSelect(pView-> newskt,pView-> m_hWnd,WM_SOCKET_MSG,FD_READFD_CLOSE);
return 1;
}

  這里之所以把accept()放到一個線程中去是因為在執行到該函數時如沒有客戶連接服務器的請求到來,服務器就會停在accept語句上等待連接請求的到來,這勢必會引起程序的阻塞,雖然也可以通過設置套接字為非阻塞方式使在沒有客戶等待時可以使accept()函數調用立即返回,但這種輪詢套接字的方式會使CPU處于忙等待方式,從而降低程序的運行效率大大浪費系統資源。考慮到這種情況,將套接字設置為阻塞工作方式,并為其單獨開辟一個子線程,將其阻塞控制在子線程范圍內而不會造成整個應用程序的阻塞。對于網絡事件的響應顯然要采取異步選擇機制,只有采取這種方式才可以在由網絡對方所引起的不可預知的網絡事件發生時能馬上在進程中做出及時的響應處理,而在沒有網絡事件到達時則可以處理其他事件,這種效率是很高的,而且完全符合Windows所標榜的消息觸發原則。前面那段代碼中的WSAAsyncSelect()函數便是實現網絡事件異步選擇的核心函數。
通過第四個參數注冊應用程序感興取的網絡事件,在這里通過FD_READFD_CLOSE指定了網絡讀和網絡斷開兩種事件,當這種事件發生時變會發出由第三個參數指定的自定義消息WM_SOCKET_MSG,接收該消息的窗口通過第二個參數指定其句柄。在消息處理函數中可以通過對消息參數低字節進行判定而區別出發生的是何種網絡事件:

void CNetServerView::OnSocket(WPARAM wParam,LPARAM lParam)
{
int iReadLen=0;
int message=lParam & 0x0000FFFF;
switch(message)
{
case FD_READ://讀事件發生。此時有字符到達,需要進行接收處理
char cDataBuffer[MTU*10];
//通過套接字接收信息
iReadLen = recv(newskt,cDataBuffer,MTU*10,0);
//將信息保存到文件
if(!file.Open("ServerFile.txt",CFile::modeReadWrite))
file.Open("E:ServerFile.txt",CFile::modeCreateCFile::modeReadWrite);

file.SeekToEnd();
file.Write(cDataBuffer,iReadLen);
file.Close();
break;
case FD_CLOSE://網絡斷開事件發生。此時客戶機關閉或退出。
……//進行相應的處理
break;
default:
break;
}
}

  在這里需要實現對自定義消息WM_SOCKET_MSG的響應,需要在頭文件和實現文件中分別添加其消息映射關系:

  頭文件:

//{{AFX_MSG(CNetServerView)
//}}AFX_MSG
void OnSocket(WPARAM wParam,LPARAM lParam);
DECLARE_MESSAGE_MAP()

  實現文件:

BEGIN_MESSAGE_MAP(CNetServerView, CView)
//{{AFX_MSG_MAP(CNetServerView)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_SOCKET_MSG,OnSocket)
END_MESSAGE_MAP()

  在進行異步選擇使用WSAAsyncSelect()函數時,有以下幾點需要引起非凡的注重:

  1. 連續使用兩次WSAAsyncSelect()函數時,只有第二次設置的事件有效,如:

WSAAsyncSelect(s,hwnd,wMsg1,FD_READ);
WSAAsyncSelect(s,hwnd,wMsg2,FD_CLOSE);

  這樣只有當FD_CLOSE事件發生時才會發送wMsg2消息。

  2.可以在設置過異步選擇后通過再次調用WSAAsyncSelect(s,hwnd,0,0);的形式取消在套接字上所設置的異步事件。

  3.Windows Sockets DLL在一個網絡事件發生后,通常只會給相應的應用程序發送一個消息,而不能發送多個消息。但通過使用一些函數隱式地答應重發此事件的消息,這樣就可能再次接收到相應的消息。

  4.在調用過closesocket()函數關閉套接字之后不會再發生FD_CLOSE事件。

  以上基本完成了服務器方的程序設計,下面對于客戶端的實現則要簡單多了,在用socket()創建完套接字之后只需通過調用connect()完成同服務器的連接即可,剩下的工作同服務器完全一樣:用send()/recv()發送/接收收據,用closesocket()關閉套接字:

sockin.sin_family=AF_INET; //地址族
sockin.sin_addr.S_un.S_addr=IPaddr; //指定服務器的IP地址
sockin.sin_port=m_Port; //指定連接的端口號
int nConnect=connect(sock,(LPSOCKADDR)&sockin,sizeof(sockin));

  本文采取的是可靠的面向連接的流式套接字。在數據發送上有write()、writev()和send()等三個函數可供選擇,其中前兩種分別用于緩沖發送和集中發送,而send()則為可控緩沖發送,并且還可以指定傳輸控制標志為MSG_OOB進行帶外數據的發送或是為MSG_DONTROUTE尋徑控制選項。在信宿地址的網絡號部分指定數據發送需要經過的網絡接口,使其可以不經過本地尋徑機制直接發送出去。這也是其同write()函數的真正區別所在。由于接收數據系統調用和發送數據系統調用是一一對應的,因此對于數據的接收,在此不再贅述,相應的三個接收函數分別為:read()、readv()和recv()。由于后者功能上的全面,本文在實現上選擇了send()-recv()函數對,在具體編程中應當視具體情況的不同靈活選擇適當的發送-接收函數對。

   小結: TCP/IP協議是目前各網絡操作系統主要的通訊協議,也是 Internet的通訊協議,本文通過Windows Sockets API實現了對基于TCP/IP協議的面向連接的流式套接字網絡通訊程序的設計,并通過異步通訊和多線程等手段提高了程序的運行效率,避免了阻塞的發生。 更多文章 更多內容請看Windows操作系統安全集  Windows操作系統安裝  Windows頻道專題,或

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲美女久久久| 欧美黑人一级爽快片淫片高清| 亚洲乱码国产乱码精品精| 日韩av第一页| 国产精品一区电影| 亚洲精品丝袜日韩| 狠狠色噜噜狠狠狠狠97| 国产成人综合精品在线| 亚洲欧美另类国产| 欧美日韩中国免费专区在线看| 久久久久久久影院| 亚洲va久久久噜噜噜| 久久久av一区| 日韩激情第一页| 久久夜色撩人精品| 国产精品尤物福利片在线观看| 国产亚洲美女精品久久久| 国产男人精品视频| 日韩在线观看你懂的| 91欧美激情另类亚洲| 久久网福利资源网站| 久久深夜福利免费观看| 在线观看不卡av| 精品久久香蕉国产线看观看亚洲| 影音先锋日韩有码| 亚洲一区二区三区四区视频| 欧美日韩在线视频一区| 96pao国产成视频永久免费| 亚洲第一av在线| 国产精品免费久久久久影院| 国产精品成人一区二区三区吃奶| 久久九九国产精品怡红院| 久久影视电视剧免费网站清宫辞电视| 国产a∨精品一区二区三区不卡| 亚洲最大福利视频网站| 日韩av影院在线观看| 色噜噜狠狠狠综合曰曰曰88av| 国产一区二区黑人欧美xxxx| 亚洲色图激情小说| 久久久国产精彩视频美女艺术照福利| 欧美精品制服第一页| 日韩国产高清视频在线| 欧美视频中文在线看| 成人www视频在线观看| 亚洲精品在线视频| 7777免费精品视频| 国产午夜一区二区| 日韩av一区二区在线| 三级精品视频久久久久| 欧美性资源免费| 国产97在线|日韩| 日韩中文字幕在线视频播放| 亚洲第一av在线| 中文字幕亚洲专区| 亚洲精品aⅴ中文字幕乱码| 亚洲一区二区三区乱码aⅴ蜜桃女| 在线电影中文日韩| 亚洲日韩欧美视频一区| 久久久免费精品视频| 久久九九免费视频| 中文日韩电影网站| 乱亲女秽乱长久久久| 91精品国产综合久久香蕉922| 欧美大胆a视频| 日韩成人中文字幕| 欧美精品手机在线| 国产精品久久久久国产a级| 揄拍成人国产精品视频| 7777免费精品视频| 午夜精品久久久久久久久久久久久| 伊人久久免费视频| 国产精品第一页在线| 欧美一区二区视频97| 高清欧美一区二区三区| 日韩av黄色在线观看| 成人在线中文字幕| 中文字幕精品网| 欧美裸体xxxxx| 亚洲国产毛片完整版| 亚洲第一精品福利| 欧美三级欧美成人高清www| 亚洲电影免费观看| 中文字幕视频在线免费欧美日韩综合在线看| 亚洲美女中文字幕| 欧美视频免费在线观看| 欧美疯狂xxxx大交乱88av| 亚洲四色影视在线观看| 亚洲欧洲高清在线| 欧美日韩国产成人在线| 裸体女人亚洲精品一区| 欧美日韩国产精品一区二区不卡中文| 成人亚洲欧美一区二区三区| 在线观看成人黄色| 国产精品日日摸夜夜添夜夜av| 一区二区欧美在线| 国产精品对白刺激| 欧美疯狂xxxx大交乱88av| 亚洲黄页视频免费观看| 欧美第一黄网免费网站| 欧美在线观看www| 欧美性视频网站| www.99久久热国产日韩欧美.com| 欧美激情综合色综合啪啪五月| 免费99精品国产自在在线| 欧美精品日韩三级| 国产精品爽爽爽爽爽爽在线观看| 91精品久久久久久久久久另类| 国产精品r级在线| 久久国产精品久久久久久久久久| 岛国av在线不卡| 国产成人综合久久| 性欧美长视频免费观看不卡| 国产婷婷色综合av蜜臀av| 亚洲wwwav| 精品性高朝久久久久久久| 久久人人爽人人爽人人片亚洲| 亚洲奶大毛多的老太婆| 18久久久久久| 欧美主播福利视频| 在线国产精品视频| 色久欧美在线视频观看| 久久久综合av| 国产精品成人免费视频| 日本精品免费观看| 国产日韩精品在线播放| 久久伊人91精品综合网站| 欧美亚洲另类激情另类| 2019亚洲男人天堂| 97国产suv精品一区二区62| 91精品国产综合久久男男| 亚洲少妇中文在线| 欧美理论片在线观看| 国产亚洲精品综合一区91| 亚洲r级在线观看| 精品美女永久免费视频| 日韩av网站导航| 欧美一级视频一区二区| 精品国产31久久久久久| 欧美激情在线播放| 91精品国产色综合久久不卡98| 欧美激情第一页xxx| 久久久91精品国产一区不卡| 欧美高跟鞋交xxxxhd| 在线成人激情黄色| 欧美精品videosex极品1| 成人天堂噜噜噜| 欧美大片在线免费观看| 91av成人在线| 亚洲乱码一区二区| 91网在线免费观看| 国产欧美一区二区白浆黑人| 97激碰免费视频| 欧美一区二粉嫩精品国产一线天| 久久在线视频在线| 精品久久在线播放| 欧美华人在线视频| 国产视频精品va久久久久久| 精品日韩美女的视频高清| 亚洲欧美日韩天堂一区二区| 亚洲区一区二区| 国产欧美婷婷中文| 91色精品视频在线| 亚洲欧美成人一区二区在线电影| 91成人福利在线|