Socket I/O模型之選擇(select)

來源:互聯網
上載者:User

http://tangfeng.iteye.com/blog/518135

在windows平台構建網路應用,必須瞭解socket I/O模型。windows提供了選擇(select)、非同步選擇(WSAAsyncSelect)、事件選擇(WSAEventSelect)、重疊I /O(overlapped I/O)和完成連接埠(completion port)。 

一、用戶端代碼 

C++代碼  
  1. #include "stdafx.h"  
  2. #include <WINSOCK2.H>  
  3. #include <stdio.h>  
  4. #pragma comment(lib, "ws2_32.lib")  
  5. #define SERVER_ADDRESS  "192.168.10.56"  
  6. #define PORT  5150  
  7. #define MSGSIZE  1024  
  8. int main(int argc, char* argv[])  
  9. {  
  10.     WSADATA wsaData;  
  11.     SOCKET sClient;  
  12.     SOCKADDR_IN server;  
  13.     char szMessage[MSGSIZE];  
  14.     int ret;  
  15.     // Initialize windows socket library  
  16.     WSAStartup(0x0202, &wsaData);  
  17.     // Create client socket  
  18.     sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
  19.     // Connect to server  
  20.     memset(&server, 0, sizeof(SOCKADDR_IN));  
  21.     server.sin_family = AF_INET;  
  22.     server.sin_addr.S_un.S_addr = inet_addr(SERVER_ADDRESS);  
  23.     server.sin_port = htons(PORT);  
  24.     connect(sClient, (sockaddr*)&server, sizeof(SOCKADDR_IN));  
  25.     while (TRUE)   
  26.     {  
  27.         printf("Send:");  
  28.         gets(szMessage);  
  29.         // Send message  
  30.         send(sClient, szMessage, strlen(szMessage), 0);  
  31.         // Receive message  
  32.         ret = recv(sClient, szMessage, MSGSIZE, 0);  
  33.         szMessage[ret] = '\0';  
  34.         printf("Received [%d bytes]: '%s'\n", ret, szMessage);  
  35.     }  
  36.     // Clean up  
  37.     closesocket(sClient);  
  38.     WSACleanup();  
  39.     return 0;  
  40. }  

這是一個最簡單的用戶端代碼,負責發送資料,然後接受返回。 

二、使用select模型的伺服器 C++代碼  

  1. // write by larry  
  2. // 2009-8-20  
  3. // This is server using select model.  
  4. #include "stdafx.h"  
  5. #include <winsock.h>  
  6. #include <stdio.h>  
  7. #define PORT  5150  
  8. #define MSGSIZE  1024  
  9. #pragma comment(lib, "ws2_32.lib")  
  10. int g_iTotalConn = 0;  
  11. SOCKET g_CliSocketArr[FD_SETSIZE];  
  12. DWORD WINAPI WorkerThread(LPVOID lpParam);  
  13. int main(int argc, char* argv[])  
  14. {  
  15.     WSADATA wsaData;  
  16.     SOCKET sListen, sClient;  
  17.     SOCKADDR_IN local, client;  
  18.     int iAddrSize = sizeof(SOCKADDR_IN);  
  19.     DWORD dwThreadId;  
  20.     // Initialize windows socket library  
  21.     WSAStartup(0x0202, &wsaData);  
  22.     // Create listening socket  
  23.     sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
  24.     // Bind  
  25.     local.sin_family = AF_INET;  
  26.     local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);  
  27.     local.sin_port = htons(PORT);  
  28.     bind(sListen, (sockaddr*)&local, sizeof(SOCKADDR_IN));  
  29.     // Listen  
  30.     listen(sListen, 3);  
  31.     // Create worker thread  
  32.     CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);  
  33.     while (TRUE)   
  34.     {  
  35.         // Accept a connection  
  36.         sClient = accept(sListen, (sockaddr*)&client, &iAddrSize);  
  37.         printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));  
  38.         // Add socket to g_CliSocketArr  
  39.         g_CliSocketArr[g_iTotalConn++] = sClient;  
  40.     }  
  41.     return 0;  
  42. }  
  43. DWORD WINAPI WorkerThread(LPVOID lpParam)  
  44. {  
  45.     int i;  
  46.     fd_set fdread;  
  47.     int ret;  
  48.     struct timeval tv = {1, 0};  
  49.     char szMessage[MSGSIZE];  
  50.     while (TRUE)   
  51.     {  
  52.         FD_ZERO(&fdread);  
  53.         for (i = 0; i < g_iTotalConn; i++)   
  54.         {  
  55.             FD_SET(g_CliSocketArr[i], &fdread);  
  56.         }  
  57.         // We only care read event  
  58.         ret = select(0, &fdread, NULL, NULL, &tv);  
  59.         if (ret == 0)   
  60.         {  
  61.             // Time expired  
  62.             continue;  
  63.         }  
  64.         for (i = 0; i < g_iTotalConn; i++)   
  65.         {  
  66.             if (FD_ISSET(g_CliSocketArr[i], &fdread))   
  67.             {  
  68.                 // A read event happened on g_CliSocketArr  
  69.                 ret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0);  
  70.                 if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))   
  71.                 {  
  72.                     // Client socket closed  
  73.                     printf("Client socket %d closed.\n", g_CliSocketArr[i]);  
  74.                     closesocket(g_CliSocketArr[i]);  
  75.                     if (i < g_iTotalConn-1)   
  76.                     {  
  77.                         g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];  
  78.                     }  
  79.                 }   
  80.                 else   
  81.                 {  
  82.                     // We reveived a message from client  
  83.                     szMessage[ret] = '\0';  
  84.                     send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);  
  85.                 }  
  86.             }  
  87.         }  
  88.     }  
  89. }  

這是非同步模型中最簡單的一種,伺服器端的幾個主要流程如下: 

1.建立監聽通訊端,綁定,監聽; 
2.建立工作者線程; 
3.建立一個通訊端數組,用來存放當前所有活動的用戶端通訊端,每accept一個串連就更新一次數組; 
4.接受用戶端的串連。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.