青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

道。道。道

安全特性不等于安全的特性

   :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理

常用鏈接

搜索

  •  

最新評論

摘要:本文對如何使用面向連接的流式套接字實(shí)現(xiàn)對網(wǎng)卡的編程以及如何實(shí)現(xiàn)異步網(wǎng)絡(luò)通訊等問題進(jìn)行了討論與闡述。

  一、 引言

  在80年代初,美國加利福尼亞大學(xué)伯克利分校的研究人員為TCP/IP網(wǎng)絡(luò)通信開發(fā)了一個(gè)專門用于網(wǎng)絡(luò)通訊開發(fā)的API。這個(gè)API就是Socket接口(套接字)--當(dāng)今在TCP/IP網(wǎng)絡(luò)最為通用的一種API,也是在互聯(lián)網(wǎng)上進(jìn)行應(yīng)用開發(fā)最為通用的一種API。在微軟聯(lián)合其它幾家公司共同制定了一套Windows下的網(wǎng)絡(luò)編程接口Windows Sockets規(guī)范后,由于在其規(guī)范中引入了一些異步函數(shù),增加了對網(wǎng)絡(luò)事件異步選擇機(jī)制,因此更加符合Windows的消息驅(qū)動特性,使網(wǎng)絡(luò)開發(fā)人員可以更加方便的進(jìn)行高性能網(wǎng)絡(luò)通訊程序的設(shè)計(jì)。本文接下來就針對Windows Sockets API進(jìn)行面向連接的流式套接字編程以及對異步網(wǎng)絡(luò)通訊的編程實(shí)現(xiàn)等問題展開討論。

  二、 面向連接的流式套接字編程模型的設(shè)計(jì)

  本文在方案選擇上采用了在網(wǎng)絡(luò)編程中最常用的一種模型--客戶機(jī)/服務(wù)器模型。這種客戶/服務(wù)器模型是一種非對稱式編程模式。該模式的基本思想是把集中在一起的應(yīng)用劃分成為功能不同的兩個(gè)部分,分別在不同的計(jì)算機(jī)上運(yùn)行,通過它們之間的分工合作來實(shí)現(xiàn)一個(gè)完整的功能。對于這種模式而言其中一部分需要作為服務(wù)器,用來響應(yīng)并為客戶提供固定的服務(wù);另一部分則作為客戶機(jī)程序用來向服務(wù)器提出請求或要求某種服務(wù)。

  本文選取了基于TCP/IP的客戶機(jī)/服務(wù)器模型和面向連接的流式套接字。其通信原理為:服務(wù)器端和客戶端都必須建立通信套接字,而且服務(wù)器端應(yīng)先進(jìn)入監(jiān)聽狀態(tài),然后客戶端套接字發(fā)出連接請求,服務(wù)器端收到請求后,建立另一個(gè)套接字進(jìn)行通信,原來負(fù)責(zé)監(jiān)聽的套接字仍進(jìn)行監(jiān)聽,如果有其它客戶發(fā)來連接請求,則再建立一個(gè)套接字。默認(rèn)狀態(tài)下最多可同時(shí)接收5個(gè)客戶的連接請求,并與之建立通信關(guān)系。因此本程序的設(shè)計(jì)流程應(yīng)當(dāng)由服務(wù)器首先啟動,然后在某一時(shí)刻啟動客戶機(jī)并使其與服務(wù)器建立連接。服務(wù)器與客戶機(jī)開始都必須調(diào)用Windows Sockets API函數(shù)socket()建立一個(gè)套接字sockets,然后服務(wù)器方調(diào)用bind()將套接字與一個(gè)本地網(wǎng)絡(luò)地址捆扎在一起,再調(diào)用listen()使套接字處于一種被動的準(zhǔn)備接收狀態(tài),同時(shí)規(guī)定它的請求隊(duì)列長度。在此之后服務(wù)器就可以通過調(diào)用accept()來接收客戶機(jī)的連接。

  相對于服務(wù)器,客戶端的工作就顯得比較簡單了,當(dāng)客戶端打開套接字之后,便可通過調(diào)用connect()和服務(wù)器建立連接。連接建立之后,客戶和服務(wù)器之間就可以通過連接發(fā)送和接收資料。最后資料傳送結(jié)束,雙方調(diào)用closesocket()關(guān)閉套接字來結(jié)束這次通訊。整個(gè)通訊過程的具體流程框圖可大致用下面的流程圖來表示:


        面向連接的流式套接字編程流程示意圖

三、 軟件設(shè)計(jì)要點(diǎn)以及異步通訊的實(shí)現(xiàn)

  根據(jù)前面設(shè)計(jì)的程序流程,可將程序劃分為兩部分:服務(wù)器端和客戶端。而且整個(gè)實(shí)現(xiàn)過程可以大致用以下幾個(gè)非常關(guān)鍵的Windows Sockets API函數(shù)將其慣穿下來:

  服務(wù)器方:

socket()->bind()->listen->accept()->recv()/send()->closesocket()

  客戶機(jī)方:

socket()->connect()->send()/recv()->closesocket()

  有鑒于以上幾個(gè)函數(shù)在整個(gè)網(wǎng)絡(luò)編程中的重要性,有必要結(jié)合程序?qū)嵗龑ζ渥鲚^深入的剖析。服務(wù)器端應(yīng)用程序在使用套接字之前,首先必須擁有一個(gè)Socket,系統(tǒng)調(diào)用socket()函數(shù)向應(yīng)用程序提供創(chuàng)建套接字的手段。該套接字實(shí)際上是在計(jì)算機(jī)中提供了一個(gè)通信埠,可以通過這個(gè)埠與任何一個(gè)具有套接字接口的計(jì)算機(jī)通信。應(yīng)用程序在網(wǎng)絡(luò)上傳輸、接收的信息都通過這個(gè)套接字接口來實(shí)現(xiàn)的。在應(yīng)用開發(fā)中如同使用文件句柄一樣,可以對套接字句柄進(jìn)行讀寫操作:

sock=socket(AF_INET,SOCK_STREAM,0);

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

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

  該函數(shù)的第二個(gè)參數(shù)是一個(gè)指向包含有本機(jī)IP地址和端口信息的sockaddr_in結(jié)構(gòu)類型的指針,其成員描述了本地端口號和本地主機(jī)地址,經(jīng)過bind()將服務(wù)器進(jìn)程在網(wǎng)絡(luò)上標(biāo)識出來。需要注意的是由于1024以內(nèi)的埠號都是保留的埠號因此如無特別需要一般不能將sockin.sin_port的埠號設(shè)置為1024以內(nèi)的值。然后調(diào)用listen()函數(shù)開始偵聽,再通過accept()調(diào)用等待接收連接以完成連接的建立:

//連接請求隊(duì)列長度為1,即只允許有一個(gè)請求,若有多個(gè)請求,
//則出現(xiàn)錯(cuò)誤,給出錯(cuò)誤代碼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_READ|FD_CLOSE);
return 1;
}

  這里之所以把a(bǔ)ccept()放到一個(gè)線程中去是因?yàn)樵趫?zhí)行到該函數(shù)時(shí)如沒有客戶連接服務(wù)器的請求到來,服務(wù)器就會停在accept語句上等待連接請求的到來,這勢必會引起程序的阻塞,雖然也可以通過設(shè)置套接字為非阻塞方式使在沒有客戶等待時(shí)可以使accept()函數(shù)調(diào)用立即返回,但這種輪詢套接字的方式會使CPU處于忙等待方式,從而降低程序的運(yùn)行效率大大浪費(fèi)系統(tǒng)資源??紤]到這種情況,將套接字設(shè)置為阻塞工作方式,并為其單獨(dú)開辟一個(gè)子線程,將其阻塞控制在子線程范圍內(nèi)而不會造成整個(gè)應(yīng)用程序的阻塞。對于網(wǎng)絡(luò)事件的響應(yīng)顯然要采取異步選擇機(jī)制,只有采取這種方式才可以在由網(wǎng)絡(luò)對方所引起的不可預(yù)知的網(wǎng)絡(luò)事件發(fā)生時(shí)能馬上在進(jìn)程中做出及時(shí)的響應(yīng)處理,而在沒有網(wǎng)絡(luò)事件到達(dá)時(shí)則可以處理其他事件,這種效率是很高的,而且完全符合Windows所標(biāo)榜的消息觸發(fā)原則。前面那段代碼中的WSAAsyncSelect()函數(shù)便是實(shí)現(xiàn)網(wǎng)絡(luò)事件異步選擇的核心函數(shù)。

  通過第四個(gè)參數(shù)注冊應(yīng)用程序感興取的網(wǎng)絡(luò)事件,在這里通過FD_READ|FD_CLOSE指定了網(wǎng)絡(luò)讀和網(wǎng)絡(luò)斷開兩種事件,當(dāng)這種事件發(fā)生時(shí)變會發(fā)出由第三個(gè)參數(shù)指定的自定義消息WM_SOCKET_MSG,接收該消息的窗口通過第二個(gè)參數(shù)指定其句柄。在消息處理函數(shù)中可以通過對消息參數(shù)低字節(jié)進(jìn)行判斷而區(qū)別出發(fā)生的是何種網(wǎng)絡(luò)事件:

void CNetServerView::OnSocket(WPARAM wParam,LPARAM lParam)
{
int iReadLen=0;
int message=lParam & 0x0000FFFF;
switch(message)
{
case FD_READ://讀事件發(fā)生。此時(shí)有字符到達(dá),需要進(jìn)行接收處理
char cDataBuffer[MTU*10];
//通過套接字接收信息
iReadLen = recv(newskt,cDataBuffer,MTU*10,0);
//將信息保存到文件
if(!file.Open("ServerFile.txt",CFile::modeReadWrite))
file.Open("E:ServerFile.txt",CFile::modeCreate|CFile::modeReadWrite);
file.SeekToEnd();
file.Write(cDataBuffer,iReadLen);
file.Close();
break;
case FD_CLOSE://網(wǎng)絡(luò)斷開事件發(fā)生。此時(shí)客戶機(jī)關(guān)閉或退出。
……//進(jìn)行相應(yīng)的處理
break;
default:
break;
}
}

  在這里需要實(shí)現(xiàn)對自定義消息WM_SOCKET_MSG的響應(yīng),需要在頭文件和實(shí)現(xiàn)文件中分別添加其消息映射關(guān)系:

  頭文件:

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

  實(shí)現(xiàn)文件:

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

  在進(jìn)行異步選擇使用WSAAsyncSelect()函數(shù)時(shí),有以下幾點(diǎn)需要引起特別的注意:

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

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

  這樣只有當(dāng)FD_CLOSE事件發(fā)生時(shí)才會發(fā)送wMsg2消息。

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

  3.Windows Sockets DLL在一個(gè)網(wǎng)絡(luò)事件發(fā)生后,通常只會給相應(yīng)的應(yīng)用程序發(fā)送一個(gè)消息,而不能發(fā)送多個(gè)消息。但通過使用一些函數(shù)隱式地允許重發(fā)此事件的消息,這樣就可能再次接收到相應(yīng)的消息。

  4.在調(diào)用過closesocket()函數(shù)關(guān)閉套接字之后不會再發(fā)生FD_CLOSE事件。

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

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

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

  小結(jié):TCP/IP協(xié)議是目前各網(wǎng)絡(luò)操作系統(tǒng)主要的通訊協(xié)議,也是 Internet的通訊協(xié)議,本文通過Windows Sockets API實(shí)現(xiàn)了對基于TCP/IP協(xié)議的面向連接的流式套接字網(wǎng)絡(luò)通訊程序的設(shè)計(jì),并通過異步通訊和多線程等手段提高了程序的運(yùn)行效率,避免了阻塞的發(fā)生。
posted on 2007-01-31 11:32 獨(dú)孤九劍 閱讀(1511) 評論(0)  編輯 收藏 引用 所屬分類: network protocol
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            在线午夜精品| 午夜影视日本亚洲欧洲精品| 欧美+亚洲+精品+三区| 在线欧美日韩精品| 亚洲人午夜精品免费| 国产精品美女主播在线观看纯欲| 亚洲国产激情| 久久久久欧美精品| 亚洲精品无人区| 亚洲欧美日韩精品久久奇米色影视| 99视频超级精品| 国产精品亚洲人在线观看| 亚洲人成人99网站| 在线视频国内自拍亚洲视频| 亚洲精品视频一区| 亚洲精选久久| 欧美美女bbbb| 久久国产精品一区二区三区四区| 亚洲国产高清aⅴ视频| 销魂美女一区二区三区视频在线| 欧美国产欧美亚洲国产日韩mv天天看完整 | 亚洲日本欧美天堂| 欧美日韩精品免费观看| 亚洲视频免费观看| 国产欧美日韩一区| 野花国产精品入口| 欧美日韩国产限制| 日韩网站在线| 性一交一乱一区二区洋洋av| 欧美视频一区在线| 亚洲在线电影| 日韩视频在线你懂得| 欧美成熟视频| 欧美一级在线播放| 一区二区三区福利| 欧美激情一区二区| 久久综合久久88| 久久婷婷久久| 欧美亚洲一级片| 亚洲精品男同| 久久高清免费观看| 一区二区欧美日韩| 国产精品高潮粉嫩av| 老司机精品导航| 亚洲伦理久久| 尤物视频一区二区| 国产精品www网站| 能在线观看的日韩av| 一区二区三区免费看| 亚洲大片免费看| 中文国产一区| 国产精品久久久久9999高清| 久久精品成人一区二区三区蜜臀| 国产嫩草影院久久久久| 久久亚洲欧美国产精品乐播| 99这里有精品| 亚洲人成人一区二区在线观看| 国产精品久久久久一区二区三区共| 国产精品久久精品日日| 亚洲国产婷婷综合在线精品| 久久激情中文| 快播亚洲色图| 久久嫩草精品久久久精品一| 欧美一区成人| 久久精品国产久精国产一老狼| 欧美日产在线观看| 欧美福利一区二区三区| 国产精品观看| 国产一区二区三区免费观看| 中文高清一区| 欧美日韩视频| 亚洲丝袜av一区| 亚洲欧美电影在线观看| 国产精品成人一区二区三区夜夜夜| 亚洲欧美日韩直播| 国产精品亚洲аv天堂网| 亚洲免费视频一区二区| 欧美亚洲视频在线看网址| 国产精品系列在线| 久久精品道一区二区三区| 欧美成人xxx| 日韩视频精品在线| 国产精品久久久久77777| 亚洲欧美日韩国产综合在线 | 欧美大片网址| 亚洲日本成人| 亚洲一区中文| 国产视频一区在线| 麻豆亚洲精品| 一本一本久久a久久精品综合妖精| 在线成人中文字幕| 欧美激情偷拍| 午夜免费日韩视频| 久久综合色播五月| 亚洲一级免费视频| 亚洲免费在线精品一区| 久久久久高清| 亚洲欧美日韩国产另类专区| 欧美日韩激情小视频| 亚洲精品免费一区二区三区| 美国成人直播| 久久人人爽人人| 亚洲电影免费在线| 亚洲精品日韩在线| 久久不射电影网| 国产美女精品视频免费观看| 久久久久久香蕉网| 日韩一级片网址| 免费亚洲一区| 午夜一区二区三区不卡视频| 亚洲区第一页| 一区二区三区精品视频| 久久久久久综合| 亚洲一区二区三区四区在线观看 | 日韩一级精品视频在线观看| 欧美激情视频一区二区三区在线播放| 99国产精品99久久久久久| 久久成人精品| 免费人成网站在线观看欧美高清| 久久久国产精品一区二区中文| 久久成人精品无人区| 欧美激情影音先锋| 国产精品a级| 欧美韩日一区| 国产欧美日韩一区二区三区在线| 欧美一区免费视频| 国产精品爽爽爽| 午夜免费日韩视频| 久久久91精品国产| 午夜精品在线| 欧美日韩专区在线| 免费观看成人网| 国内精品久久久久久久影视蜜臀| 一区二区三区国产精华| 欧美影院午夜播放| 亚洲综合电影一区二区三区| 亚洲国产精品一区二区三区| 国产精品视频xxxx| 亚洲视频一二三| 亚洲一区精品电影| 国产精品久久久久久户外露出| 91久久中文| 美国十次成人| 久久久噜噜噜久久久| 麻豆国产精品va在线观看不卡| 欧美专区亚洲专区| 久久久九九九九| 国户精品久久久久久久久久久不卡| 9色porny自拍视频一区二区| 亚洲欧洲精品一区二区三区波多野1战4 | 久久九九免费| 一区二区三区在线视频观看| 狼狼综合久久久久综合网| 亚洲欧美日韩综合国产aⅴ| 蜜臀久久久99精品久久久久久| 国产精品福利网站| 一本大道久久a久久综合婷婷| 欧美四级在线| 欧美怡红院视频| 裸体歌舞表演一区二区| 亚洲美女少妇无套啪啪呻吟| 国产精品video| 美日韩精品视频| 亚洲免费视频在线观看| 欧美中文字幕久久| 亚洲精品国产系列| 亚洲级视频在线观看免费1级| 欧美国产综合视频| 欧美日韩国产大片| 欧美视频一区二区三区四区| 国产精品永久在线| 在线精品福利| 日韩视频免费看| 先锋影院在线亚洲| 蜜臀va亚洲va欧美va天堂| 91久久国产综合久久| 亚洲一级网站| 久久免费偷拍视频| 欧美精品999| 国产欧美在线| 亚洲精品国产无天堂网2021| 亚洲女女做受ⅹxx高潮| 久久综合久久久| 在线视频欧美日韩| 久久乐国产精品| 国户精品久久久久久久久久久不卡 | 亚洲午夜激情| 日韩一区二区福利| 国产精品99久久久久久www| 亚洲一区中文| 性欧美长视频| 欧美1区2区| 国产精品爱啪在线线免费观看| 午夜一区二区三区在线观看| 亚洲国产日韩欧美| 亚洲一区二区黄色| 亚洲欧美日韩国产一区二区三区| 国产精品电影观看| 亚洲福利视频一区二区| 午夜精品免费在线|