select模型使用例子

在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.接受客户端的连接。

你可能感兴趣的:(windows,socket,server,Stream,null,winapi)