版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Winsocket 入門教程一:多線程阻塞式服務(wù)器和阻塞式客戶端程序 (TCP)Winsocket入門教程一:多線程阻塞式服務(wù)器和阻塞式客戶端程序(TCP)收藏最近因?yàn)楣ぷ餍枰獙W(xué)習(xí)了 Winsocket 客戶端服務(wù)器模型程序的設(shè)計(jì)。在學(xué)習(xí)的過程中,我發(fā)現(xiàn)學(xué)習(xí) Winsocket 的資料不多并且十分的零散。我一直沒有找到一本學(xué)習(xí) Winsocket 方面的經(jīng)典國外著作。而且這些資料中并沒有提供源代碼文件, 所以我只有將這些源代碼在自己敲一遍。在敲代碼的過程中, 我發(fā)現(xiàn)了這些源代碼中的一些錯(cuò)誤的地方和一些已經(jīng)過時(shí)的 Windows 程序的輸寫方法 (Win16?) 。現(xiàn)將學(xué)習(xí)經(jīng)驗(yàn)和通過閱讀各種資料
2、總結(jié)出來的模型以及代碼分享出來。希望對學(xué)習(xí) Winsocket 的初學(xué)者有一定的幫助。我們首先來了解一下什么是t 。Winsocket是 unix/linuxWinsocke下的 berkeleyinuxsocket 下的在 Windows下的實(shí)現(xiàn)。 unix/lberkeleysocket是網(wǎng)絡(luò)通訊方面的基石,應(yīng)用程序通過調(diào)用berkeleysocket的 API進(jìn)行相互通訊, berkeleysocket 則利用具體的網(wǎng)絡(luò)通訊協(xié)議和操作系統(tǒng)的調(diào)用來為我們完成具體的通訊工作。 Winsocket保留了 berkeleysocket的所有內(nèi)容,并且為了其能在 Win32消息機(jī)制和多線程的環(huán)境下
3、更好的工作。 Winsocket在 berkeleysocket 原有的基礎(chǔ)上對其進(jìn)行了擴(kuò)充。如我們可以利用 WSAAsyncSelect對 Socket消息進(jìn)行訂閱,以及使用WSAGetLastError對多線程環(huán)境下的 Winsocket錯(cuò)誤進(jìn)行捕獲。接著再讓我們來了解一下服務(wù)器 客戶端應(yīng)用程序模型。該模型是構(gòu)建分布式系統(tǒng)的模型之一。服務(wù)器程序一直處于監(jiān)聽的狀態(tài), 等待客戶端程序的連接。 客戶端程序像服務(wù)器程序發(fā)送連接請求,服務(wù)器程序接受該連接請求, 同時(shí)與客戶端程序建立連接。 此時(shí)客戶端程序就可以向服務(wù)器發(fā)送具體的請求, 獲取相關(guān)的數(shù)據(jù)。 服務(wù)器 客戶端模型有三種連接方式,一種是面向連接
4、的 (TCP) ,面向連接的服務(wù)是一種可靠的服務(wù),它通過數(shù)據(jù)流進(jìn)行數(shù)據(jù)的傳輸, 面向連接的服務(wù)實(shí)現(xiàn)了無差錯(cuò)無重復(fù)的順尋數(shù)據(jù)發(fā)送。 一種是面向無連接的 (UDP) ,面向無連接的服務(wù)是一種不可靠的服務(wù),它通過數(shù)據(jù)報(bào)進(jìn)行數(shù)據(jù)傳輸,由于數(shù)據(jù)報(bào)進(jìn)行傳輸時(shí)的順序是無序的, 所以它是不可靠的服務(wù)。最后一種是多播的方式,及服務(wù)器程序主動(dòng)向多個(gè)客戶端程序發(fā)送信息。面向連接的服務(wù)器 客戶端應(yīng)用程序模型的程序 流 程 圖 如 下 所 示 :在此模型的阻塞模式中, 服務(wù)端程序在執(zhí)行 a ccept 操作、客戶端程序 connect 操作、以及服務(wù)端 客戶端在進(jìn)行 read 和 write 操作時(shí),如果這些操作既沒有
5、成功也沒有失敗, 應(yīng)用程序會(huì)在執(zhí)行這些操作的地方一直阻塞著。 所以我們應(yīng)該在服務(wù)端應(yīng)用程序的主線程中不停的調(diào)用 accept 操作,以使服務(wù)端程序能不停地接受客戶端程序發(fā)送過來的連接請求。 而在接受了一個(gè)客戶端的連接請求后, 我們應(yīng)改為每一個(gè)接受的連接請求開辟一個(gè)專門的線程來接受客戶端程序發(fā)送的請求以及為具體的請求返回特定的信息。根據(jù)以上的程序流程圖以及說明,我們可以寫出以下的服務(wù)端程序源代碼:viewplaincopytoclipboardprint?1. /2. / file ServerMultThreadServerMultThread.cpp3. /4. / brief 阻塞式多線程
6、服務(wù)器程序。 每當(dāng)客戶端程序請求與服務(wù)端連接時(shí),服務(wù)端程序開放一個(gè)線程接受客戶端程序的請求5. /并且向客戶端回饋請求的信息。客戶端請求的信息輸出到控制臺(tái)中.6. /7. #include 8. #include 9. #include 10. #include 11. #pragma comment(lib, ws2_ 32.lib )12. #define ASSERT assert13. #define THREAD HANDLE14. #define EVENT HANDLE15. #define CloseThread CloseHandle16. #define CloseEven
7、t CloseHandle17. using std:cin;18. using std:cout;19. using std:endl;20. /21. / struct tagServerRecv22. /23. / brief 線程函數(shù)參數(shù)結(jié)構(gòu)體,其中包含已建立連接的 socket.24. /25. / author Shining10026. / date 2010-05-1827. /28. typedef struct tagServerRecv29. 30.SOCKET skAccept;/已建立連接的 socket31.CRITICAL_SECTION *pcs; / 同步控制
8、臺(tái)輸出的臨界區(qū)32.EVENTe;/保證結(jié)構(gòu)體各個(gè)字段在結(jié)構(gòu)體字段改變之前將其拷貝到線程中的信號量33.THREAD t;/當(dāng)前線程的內(nèi)核對象34.DWORDdwThreadID;/ 當(dāng)前線程的 ID35. SERVER_RECV, *PSERVER_RECV;36. /37. / fn static int ServerRecv(L PVOID lParam)38. /39. / brief 服務(wù)器與建立連接的客戶端進(jìn)行通訊 .40. /41. / author Shining10042. / date 2010-05-1843. /44./ param lParam線程函數(shù)參數(shù) , 詳細(xì)信
9、息見上面說明 .45. /46./ return總是返回 0.47. /48. static int ServerRecv( LPVOID l Param);49.static constint c_iPort = 10001;50.int main()51.52.int iRet = SOCKET_ERROR;53./初始化 Winsocket,所有socket程序必須先使用WSAStartupWin進(jìn)行初始化54.WSADATA data;55. ZeroMemory(&data, sizeof (WSADATA);56. iRet = WSAStartup(MAKEW ORD(2, 0)
10、, &data);57. ASSERT(SOCKET_ERROR != i Ret);58./建立服務(wù)端程序的監(jiān)聽套接字59. SOCKET skListen = INVALID _SOCKET;60. skListen = socket(AF_INE T, SOCK_STREAM, 0);61.ASSERT(INVALID_SOCKET != skListen);62./初始化監(jiān)聽套接字地址信息63.sockaddr_in adrServ;/表示網(wǎng)絡(luò)地址64. ZeroMemory(&adrServ, size of(sockaddr_in);65.adrServ.sin_family= A
11、F_INET;/初始化地址格式,只能為AF_INET66.adrServ.sin_port= hton初始化端口,由于網(wǎng)絡(luò)字節(jié)順序和主機(jī)字節(jié)順序相反, 所以必須使用 h tons 將主機(jī)字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序67.adrServ.sin_addr.s_addr = INADDR_ANY;/初始化 IP ,由于是服務(wù)器程序,所以可以將 INADDR_AN Y 賦給該字段,表示任意的 IP68./綁定監(jiān)聽套接字到本地69. iRet = bind(skListen, (socka ddr*)&adrServ, sizeof(sockaddr_i n);70.ASSERT(SOCKET_ERRO
12、R != iRet);71./使用監(jiān)聽套接字進(jìn)行監(jiān)聽72.iRet = listen(skListen, SOMAXCONN); / SOMAXCONN表示可以連接到該程序的最大連接數(shù)73.ASSERT(SOCKET_ERROR != iRet);74./輸出控制臺(tái)緩沖區(qū),由于可能有多個(gè)客戶端程序可能同時(shí)向緩沖區(qū)發(fā)送請求信息75./為了保證輸出時(shí)能夠一次性完整的輸出完一個(gè)客戶端的請求信息,所以在輸出客76./戶程序的信息到控制臺(tái)時(shí),必須使用臨界區(qū)阻塞其它線程77.CRITICAL_SECTION cs;78.InitializeCriticalSection(&cs);79./保證結(jié)構(gòu)體各個(gè)字
13、段在結(jié)構(gòu)體字段改變之前將其拷貝到線程中的信號量80./因?yàn)楫?dāng)該結(jié)構(gòu)體拷貝到線程中之前 , 有可能有新的連接到來并改變了結(jié)構(gòu)體的值81./所以我們必須先保證值拷貝過后再接受連接82.EVENT e = NULL;83.e = CreateEvent(NULL, FALSE, FALSE, NULL);84.ASSERT(NULL != e);85.for(;)86.87./客戶端向服務(wù)器端發(fā)送連接請求,服務(wù)器端接受客戶端的連接88. SOCKET skAccept = INVA LID_SOCKET;89.sockaddr_in adrClit;90. ZeroMemory(&adrClit,
14、siz eof(sockaddr_in);91. int iLen = sizeof(sockaddr _in);92. skAccept = accept(skListe n, (sockaddr*)&adrClit, &iLen); / 如果沒有客戶端程序請求連接,服務(wù)端程序會(huì)一直阻塞在這里等待連接93.ASSERT(INVALID_SOCKET != skAccept);94.SERVER_RECV sr;95./成功創(chuàng)建連接后創(chuàng)建一個(gè)獨(dú)立的線程應(yīng)答客戶請求,以防止應(yīng)用程序因?yàn)樽枞麩o法應(yīng)答新的客戶請求96./我們應(yīng)該先將線程掛起,以便我們能夠在線程執(zhí)行之前初始化線程所需要的結(jié)構(gòu)體變量中的
15、各個(gè)字段97.THREAD hThread= NULL;98.DWORDdwThreadID = 0;99.hThread = CreateThread(NULL, 0, (LPTHREAD_START_RO UTINE)ServerRecv,100. &sr, CREATE_SUSPEND ED, &dwThreadID);101. ASSERT(NULL != hThrea d);102./初始化結(jié)構(gòu)體字段103.sr.skAccept= skAccept;104.sr.pcs= &cs;105.sr.e= e;106.sr.t= hThread;107.sr.dwThreadID = d
16、wThreadID;108./啟動(dòng)線程109.DWORD dwRet = ResumeThread(hThread);110.ASSERT(-1 != dwRet);111.112./保證結(jié)構(gòu)體被拷貝到線程中后再應(yīng)答新的連接113. dwRet = WaitForSingleOb ject (e, INFINITE);114.ASSERT(WAIT_FAILED != dwRet);115. 116. / 清理線程同步資源117. DeleteCriticalSection(&cs);118.BOOLbRet = FALSE;119. bRet = CloseEvent(e);120. ASS
17、ERT(bRet);121. / 關(guān)閉該套接字的連接122. iRet = shutdown(skListen, S D_SEND);123. ASSERT(SOCKET_ERROR != i124./清理該套接字的資源125. iRet = closesocket(skListen);126. ASSERT(SOCKET_ERROR != iRet);127./清理 Winsocket資源128. iRet = WSACleanup();129. ASSERT(SOCKET_ERROR != iRet);130. cin.get();131. return 0;132. 133. int S
18、erverRecv(LPVOID lParam)134. 135. / 拷貝結(jié)構(gòu)體各個(gè)字段到線程中136. PSERVER_RECV psr = (PSERVER_RECV)lParam;137. SERVER_RECV sr = 138.psr-skAccept,139.psr-pcs,140.psr-e,141.psr-t,142.psr-dwThreadID143. ;144. / 設(shè)置信號量, 使主線程能夠接受新的連接145.BOOLbRet = FALSE;146. bRet = SetEvent(sr.e);147. ASSERT(bRet);148.constintc_iBufL
19、en = 512;149.charszBufc_iBufLen + 1 = 0;150.constchar c_szPrefix = Server recv:;151.constintc_iPrefLen = strlen(c_szPrefix);152.charszRelyc_iBufLen + 16 + 1 = 0;153. strcpy(szRely, c_szPrefix);154.intiRet = SOCKET_ERROR;155. for(;)156. 157.iRet = recv(sr.skAccept, szBuf, c_iBufLen, 0); /接收客戶端發(fā)送的信息,
20、如果客戶端不發(fā)送信息,則線程會(huì)阻塞到此處158.if(0 = iRet) /客戶端優(yōu)雅的關(guān)閉了此連接159.160.cout Connection sr.dwThreadID shutdown. endl;161.break;162.163.else if(SOCKET_ERROR = iRet) / 客戶端粗魯?shù)年P(guān)閉了此連接或者接受信息出錯(cuò)164.165.cout Connection sr.dwThreadID recv error. endl;166.break;167.168.szBufiRet = 0;169.EnterCriticalSection(sr.pcs);170.cout
21、 Connection sr.dwThreadID says: szBuf endl; /輸出接收到的信息171.LeaveCriticalSection(sr.pcs);172./向客戶端發(fā)送信息173.strcpy(szRely + c_iPrefLen, szBuf);174.iRet = send(sr.skAccept, szRely, strlen(szRely), 0); /客戶端如果沒有足夠的緩沖區(qū)接受信息,則線程會(huì)阻塞到此處175. if(SOCKET_ERROR = iRe t)176.177. cout Connectio n sr.dwThreadID sen d er
22、ror. 0);184. ASSERT(SOCKET_ERROR != i185./清理該套接口的資源186. iRet = closesocket(sr.skAccept);187. ASSERT(SOCKET_ERROR != iRet);188./關(guān)閉該線程對象189. bRet = CloseThread(sr.t);190. ASSERT(bRet);191. cout Connection sr. dwThreadID exit. endl;192. return 0;193. / fileServerMultThreadServerMultThread.c/ brief阻塞式多線
23、程服務(wù)器程序。每當(dāng)客戶端程序/并且向客戶端回饋請求的信息???#include #include #include #include #pragma comment(lib, ws2_32.lib )#define ASSERT assert#define THREAD HANDLE#define EVENT HANDLE#define CloseThread CloseHandle#define CloseEvent CloseHandleusing std:cin;using std:cout;在用 Winsocket編寫程序時(shí),我們首先必須要進(jìn)行如下的操作,以為該進(jìn)程初始化Winsock
24、et和 Ws2_32.dll,而使后面的函數(shù)調(diào)用有效。viewplaincopytoclipboardprint?1. WSADATA data;2. ZeroMemory(&data, sizeof(WSAD ATA);3. iRet = WSAStartup(MAKEWORD (2, 0), &data);4. ASSERT(SOCKET_ERROR != iRet);WSADATA data;ZeroMemory(&data, sizeof(WSADATA);iRet = WSAStartup(MAKEWORD(2, 0), &data);ASSERT(SOCKET_ERROR != i
25、Ret);WSAStartup第一個(gè)參數(shù)為要使用的Winsocket的版本, MAKEWORD(2,0)表示我們使用 Winsocket2.0。第二個(gè)參數(shù)在WSAStartup初始化后,可以獲得一些Winsocket相關(guān)信息,如該版本W(wǎng)insocket所支持的最大 socket 數(shù)量以及 UDP 包的最大大小。在初始化了 Winsocket 后,我們就可以創(chuàng)建一個(gè) socket 監(jiān)聽客戶端的連接請求了。viewplaincopytoclipboardprint?1. SOCKET skListen = INVALID_SOC KET;2. skListen = socket(AF_INET,
26、SOC K_STREAM, 0);3. ASSERT(INVALID_SOCKET != skListen);SOCKET skListen = INVALID_SOCKET;skListen = socket(AF_INET, SOCK_STREAM, 0);ASSERT(INVALID_SOCKET != skListen);s ocket函數(shù)分配相應(yīng)的資源并將該socket綁定到一個(gè)特定的傳輸服務(wù)提供者。socket的第一個(gè)參數(shù)為網(wǎng)絡(luò)地址族, 該參數(shù)只能為 AF_INET ,第二個(gè)參數(shù)可以為SOCK_STREAM或者 SOCK_DGRAM 。SOCK_STREAM 為一個(gè)流式套接口, 它
27、提供雙向可靠、面向連接的 TCP 服務(wù)。SOCK_DGRAM 為一個(gè)數(shù)據(jù)報(bào)套接口,它提供不可靠、面向無連接的 UDP 服務(wù)。第三個(gè)參數(shù)一般選擇為0 ,表示由 Winsocket 選擇具體的協(xié)議使用。在建立了一個(gè)監(jiān)聽 socket 后,我們就可以將該套接口與本地地址進(jìn)行綁定, 已將其設(shè)置成為網(wǎng)絡(luò)中一個(gè)獨(dú)一無二的地址。viewplaincopytoclipboardprint?1. iRet = bind(skListen, (sockaddr*) &adrServ, sizeof(sockaddr_in);2. ASSERT(SOCKET_ERROR != iRet);iRet = bind(s
28、kListen, (sockaddr*)&adrServ, sizeof(sASSERT(SOCKET_ERROR != iRet);在綁定了本地地址后, 我們就可以將該 s ocket 設(shè)置為監(jiān)聽狀態(tài),以使該 socket 可以檢測到來自客戶端程序的連接請求。viewplaincopytoclipboardprint?1. iRet = listen(skListen, SOMAXCONN); / SOMAXCONN表示可以連接到該程序的最大連接數(shù)2. ASSERT(SOCKET_ERROR != iRet);iRet = listen(skListen, SOMAXCONN); / SOM
29、AXCONN表示ASSERT(SOCKET_ERROR != iRet);接下來我們我們就可以利用套接口接受來自客戶端程序的連接了。 我們以該套接口為參數(shù)調(diào)用 accept 函數(shù),accept 函數(shù)調(diào)用成功后, 將建立一個(gè)可以接受和發(fā)送數(shù)據(jù)的套接口 skAcc ept 。viewplaincopytoclipboardprint?1. / 客戶端向服務(wù)器端發(fā)送連接請求,服務(wù)器端接受客戶端的連接2. SOCKET skAccept = INVALID_SO CKET;3. sockaddr_in adrClit;4. ZeroMemory(&adrClit, sizeof(soc kaddr_i
30、n);5. int iLen = sizeof(sockaddr_in);6. skAccept = accept(skListen, (sockaddr*)&adrClit, &iLen); /如果沒有客戶端程序請求連接,服務(wù)端程序會(huì)一直阻塞在這里等待連接7. ASSERT(INVALID_SOCKET != skAccept);/ 客戶端向服務(wù)器端發(fā)送連接請求,服務(wù)器端接受客戶端的連SOCKET skAccept = INVALID_SOCKET; sockaddr_in adrClit; ZeroMemory(&adrClit, sizeof(sockaddr_in); int iLen
31、 = sizeof(sockaddr_in);skAccept = accept(skListen, (sockaddr*)&adrClit, &i ASSERT(INVALID_SOCKET != skAccept);在成功的建立了新套接口后, 我們就可以利用該套接口在我們的線程函數(shù)中接收和發(fā)送數(shù)據(jù)了。viewplaincopytoclipboardprint?1. iRet = recv(sr.skAccept, szBuf, c_iBufLen, 0); /接收客戶端發(fā)送的信息, 如果客戶端不發(fā)送信息,則線程會(huì)阻塞到此處2.if(0 = iRet) /客戶端優(yōu)雅的關(guān)閉了此連接3.4.co
32、ut Connection sr.dwThreadID shutdown. endl;5.break;6.7.else if(SOCKET_ERROR = iRet) /客戶端粗魯?shù)年P(guān)閉了此連接或者接受信息出錯(cuò)8.9.cout Connection sr.dwThreadID recv error. endl;10.break;.12.szBufiRet = 0;iRet = recv(sr.skAccept, szBuf, c_iBufLen, 0); /接if(0 = iRet) /客戶端優(yōu)雅的關(guān)閉了此cout Connection srbreak;else if(SOCK
33、ET_ERROR = iRet) /客cout Connection srbreak;szBufiRet = 0;viewplaincopytoclipboardprint?1. strcpy(szRely + c_iPrefLen, szBu f);2.iRet = send(sr.skAccept, szRely, strlen(szRely), 0); /客戶端如果沒有足夠的緩沖區(qū)接受信息,則線程會(huì)阻塞到此處if(SOCKET_ERROR = iRet)cout Connection sr.dwThreadID send error. endl;6.break;7.strcpy(szRe
34、ly + c_iPrefLen, szBuf);iRet = send(sr.skAccept, szRely, stif(SOCKET_ERROR = iRet)cout Connection 0);4. ASSERT(SOCKET_ERROR != iRet);5./清理該套接口的資源6. iRet = closesocket(sr.skAccept);7. ASSERT(SOCKET_ERROR != iRet);/ 關(guān)閉該套接口iRet = shutdown(sr.skAccept, SD_SEND);while(recv(sr.skAccept, szBuf, c_iBufLen,
35、0ASSERT(SOCKET_ERROR != iRet);/ 清理該套接口的資源iRet = closesocket(sr.skAccept);ASSERT(SOCKET_ERROR != iRet);監(jiān)聽 socket 的關(guān)閉也與上面套接口關(guān)閉的方法一致。 在關(guān)閉了監(jiān)聽套接口后, 我們的服務(wù)器程序應(yīng)該調(diào)用 WSACleanup 函數(shù),已完成對 Winsocket 和 ws2_32.dll 的清理。上述就是該類型服務(wù)器程序應(yīng)用程序執(zhí)行的全過程了。客戶端程序的代碼跟服務(wù)器程序的代碼相似,程序代碼如下所示:viewplaincopytoclipboardprint?1. /2. / file C
36、lientBlockClientBloc k.cpp3. /4. / brief 連接服務(wù)器并向服務(wù)器發(fā)送信息,然后接受服務(wù)器發(fā)送的信息 .5. /6. #include 7. #include 8. #include 9. #pragma comment(lib, ws2_32. lib )10. #define ASSERT assert11. using std:cin;12. using std:cout;13. using std:endl;14.static constcharc_szIP = ;15.static constintc_iPort = 10001;
37、16. int main()17. 18. int iRet = SOCKET_ERRO R;19./初始化 Winsocket,所有socket程序必須先使用WSAStartupWin進(jìn)行初始化20.WSADATA data;21.ZeroMemory(&data, sizeof(WSADATA);22.iRet = WSAStartup(MAKEWORD(2, 0), &data);23.ASSERT(SOCKET_ERROR != iRet);24./建立連接套接字25.SOCKET skClient = INVALID_SOCKET;26.skClient = socket(AF_IN
38、ET, SOCK_STREAM, 0);27.ASSERT(INVALID_SOCKET != skClient);28./ 初始化連接套接字地址信息29.sockaddr_in adrServ;/表示網(wǎng)絡(luò)地址30.ZeroMemory(&adrServ, sizeof(sockaddr_in);31.adrServ.sin_family= AF_INET;/初始化地址格式, 只能為AF_INET32.adrServ.sin_port= htons(c_iPort);/初始化端口,由于網(wǎng)絡(luò)字節(jié)順序和主機(jī)字節(jié)順序相反,所以必須使用 htons 將主機(jī)字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序33.adrServ
39、.sin_addr.s_addr = inet_addr(c_szIP);/初始化 IP ,由于網(wǎng)絡(luò)字節(jié)順序和主機(jī)字節(jié)順序相反,所以必須使用 inet_addr 將主機(jī)字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序34./使用連接套接字進(jìn)行連接35. iRet = connect(skClient, (so ckaddr*)&adrServ, sizeof(sockad dr_in);36. ASSERT(SOCKET_ERROR != i Ret);37.constint c_iBufLen = 512;38.charszBufc_iBufLen + 16 + 1 = 0;39.for(;)40.41.cout
40、 szBuf;43.if(0 = strcmp(exit, szBuf)44.45.break;46.47./向服務(wù)器端發(fā)送信息48.iRet = send(skClient, szBuf, strlen(szBuf), 0); /服務(wù)器端如果沒有足夠的緩沖區(qū)接受信息,則線程會(huì)阻塞到此處49.if(SOCKET_ERROR = iRet)50.51.cout send error. endl;52.break;53.54./接收服務(wù)器端發(fā)送的信息55.iRet = recv(skClient, szBuf, c_iBufLen, 0); /如果服務(wù)器端沒有發(fā)送數(shù)據(jù),則會(huì)阻塞到此處56.if(0 = iRet)57.58.cout connection shu
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- GB/T 26635-2025動(dòng)植物油脂生育酚及生育三烯酚含量測定高效液相色譜法
- 2026年反網(wǎng)絡(luò)電信詐騙知識(shí)考試卷及答案(二)
- 2025年大學(xué)大四(通信技術(shù))通信技術(shù)前沿應(yīng)用研究階段測試題及答案
- 2025年中職(物流法律法規(guī))物流合同條款解讀階段測試試題及答案
- 2025年高職食品檢驗(yàn)檢測技術(shù)(食品微生物檢驗(yàn))試題及答案
- 2025年大學(xué)食品質(zhì)量與安全(食品毒理學(xué))試題及答案
- 2025年大學(xué)大四(設(shè)計(jì)學(xué))設(shè)計(jì)創(chuàng)新基礎(chǔ)理論測試題及答案
- 2025年高職(直播電商運(yùn)營)直播話術(shù)設(shè)計(jì)綜合測試題
- 2025年大學(xué)林學(xué)(林業(yè)技術(shù)研發(fā))試題及答案
- 2025年中職護(hù)理(養(yǎng)老護(hù)理方向)(康復(fù)理療)試題及答案
- 消化內(nèi)鏡ERCP技術(shù)改良
- 云南師大附中2026屆高三1月高考適應(yīng)性月考卷英語(六)含答案
- 紀(jì)念館新館項(xiàng)目可行性研究報(bào)告
- 騎行美食活動(dòng)方案策劃(3篇)
- 2026年上海市松江區(qū)初三語文一模試卷(暫無答案)
- 石化企業(yè)環(huán)保培訓(xùn)課件
- 2026年呂梁職業(yè)技術(shù)學(xué)院單招職業(yè)技能考試備考試題帶答案解析
- 清華大學(xué)教師教學(xué)檔案袋制度
- 2025年新疆師范大學(xué)輔導(dǎo)員招聘考試真題及答案
- 人教版九年級物理上學(xué)期期末復(fù)習(xí)(知識(shí)速記+考點(diǎn)突破+考點(diǎn)練習(xí)題)含答案
- 電梯更新改造方案
評論
0/150
提交評論