服務端用非阻塞socket客戶端用阻塞socket
阿新 • • 發佈:2019-01-06
之前, 我們簡要第瞭解了一下非阻塞的socket。 在本文中, 我們讓服務端用非阻塞socket, 客戶端依然用我們熟悉的阻塞的socket.
服務端程式如下(非阻塞的socket):
執行程式, 開啟服務端程序。#include <stdio.h> #include <winsock2.h> #include <windows.h> #pragma comment(lib, "ws2_32.lib") int main() { // 網路初始化 WSADATA wsd; WSAStartup(MAKEWORD(2,2), &wsd); // 預設為阻塞socket SOCKET sServer = socket(AF_INET,SOCK_STREAM, 0); // 設定為非阻塞socket int iMode = 1; ioctlsocket(sServer, FIONBIO, (u_long FAR*)&iMode); // 設定伺服器套接字地址 SOCKADDR_IN addrServ; addrServ.sin_family = AF_INET; addrServ.sin_port = htons(8888); addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY); bind(sServer,(const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN)); // 用耳朵聽聽 listen(sServer, 5); // 接受客戶請求 printf("accept\n"); sockaddr_in addrClient; int len = sizeof(addrClient); SOCKET sClient = 0; while(1) { sClient = accept(sServer,(sockaddr FAR*)&addrClient, &len); if(INVALID_SOCKET == sClient) { int err = WSAGetLastError(); if(WSAEWOULDBLOCK == err) // 沒有客戶端來connect { Sleep(100); continue; } // 其實這裡還應該考慮一下異常比較好 } printf("accept ok\n"); break; } int iRet = -1; while(1) { char szRecvBuf[100] = {0}; iRet = recv(sClient, szRecvBuf, sizeof(szRecvBuf), 0); if(SOCKET_ERROR == iRet) { int err = WSAGetLastError(); if(WSAEWOULDBLOCK == err) // 接收socket對應的核心緩衝區中暫時沒有資料 { Sleep(100); continue; } // 這裡考慮一下異常比較好 } printf("%s\n", szRecvBuf); break; } // 網路釋放 closesocket(sServer); closesocket(sClient); WSACleanup(); return 0; }
下面, 我們看看客戶端的程式(阻塞的socket):
執行該程式。#include <winsock2.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") int main() { WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2, 2); WSAStartup( wVersionRequested, &wsaData ); SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(8888); connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); send(sockClient, "hello world", strlen("hello world") + 1, 0); closesocket(sockClient); WSACleanup(); return 0; }
服務端程序列印的結果為:
accept
accept ok
hello world
最後, 根據實踐的結果, 我不得不在這裡強調一下: 服務端的recv函式是否阻塞, 並不取決於客戶端的sockClient是否是阻塞式的, 而是取決於服務端的sServer是否為阻塞式的, 所以, 上面服務端的recv並不會阻塞。
好, 本文我們就先學到這裡。