• windows下基于异步通知IO模型的回声服务器和客户端的实现


    1. 利用异步io通知模型实现回声服务器端

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <winsock2.h>
      4 
      5 #define BUF_SIZE 100
      6 
      7 void CompressSockets(SOCKET hSockArr[], int idx, int total);
      8 void CompressEvents(WSAEVENT hEventArr[], int idx, int total);
      9 void ErrorHandling(char *msg);
     10 
     11 int main(int argc, char *argv[])
     12 {
     13     WSADATA wsaData;
     14     SOCKET hServSock, hClntSock;
     15     SOCKADDR_IN servAdr, clntAdr;
     16 
     17     SOCKET hSockArr[WSA_MAXIMUM_WAIT_EVENTS]; 
     18     WSAEVENT hEventArr[WSA_MAXIMUM_WAIT_EVENTS];
     19     WSAEVENT newEvent;
     20     WSANETWORKEVENTS netEvents;    //保存发生的事件类型信息和错误信息的结构体变量
     21 
     22     int numOfClntSock=0;
     23     int strLen, i;
     24     int posInfo, startIdx;
     25     int clntAdrLen;
     26     char msg[BUF_SIZE];
     27     
     28     if(argc!=2) {
     29         printf("Usage: %s <port>
    ", argv[0]);
     30         exit(1);
     31     }
     32     if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
     33         ErrorHandling("WSAStartup() error!");
     34 
     35     hServSock=socket(PF_INET, SOCK_STREAM, 0);
     36     memset(&servAdr, 0, sizeof(servAdr));
     37     servAdr.sin_family=AF_INET;
     38     servAdr.sin_addr.s_addr=htonl(INADDR_ANY);
     39     servAdr.sin_port=htons(atoi(argv[1]));
     40 
     41     if(bind(hServSock, (SOCKADDR*) &servAdr, sizeof(servAdr))==SOCKET_ERROR)
     42         ErrorHandling("bind() error");
     43 
     44     if(listen(hServSock, 5)==SOCKET_ERROR)
     45         ErrorHandling("listen() error");
     46 
     47     newEvent=WSACreateEvent();    //创建manual_reset模式non-signaled状态的事件对象
     48     /* 指定hServSock套接字句柄为newEvent的监视对象,希望监视的事件类型为: 有新的连接请求 */
     49     if(WSAEventSelect(hServSock, newEvent, FD_ACCEPT)==SOCKET_ERROR)
     50         ErrorHandling("WSAEventSelect() error");
     51 
     52     hSockArr[numOfClntSock]=hServSock;
     53     hEventArr[numOfClntSock]=newEvent;
     54     numOfClntSock++;
     55 
     56     while(1)
     57     {
     58         /* 验证是否发生事件,成功时返回发生事件的对象信息,只要有一个事件对象的状态变为signaled时就返回
     59          * 可通过以宏的方式申明的WSA_MAXIMUN_WAIT_EVENTS常量得知WSAWaitMulltipleEvents函数可以同时监听的最大事件对象数,该常量为64
     60          * 通过该函数可以得到转为signaled状态的事件对象中的第一个(按数组中的保存顺序)索引值, 返回值减去常量WSA_WAIT_EVENT_0,可以得到
     61          * 转变为signaled状态的事件对象句柄
     62          */
     63         posInfo=WSAWaitForMultipleEvents(
     64             numOfClntSock, hEventArr, FALSE, WSA_INFINITE, FALSE);
     65         startIdx=posInfo-WSA_WAIT_EVENT_0;
     66         /* 获取所有signaled状态的事件对象 */
     67         for(i=startIdx; i<numOfClntSock; i++)
     68         {
     69             int sigEventIdx=
     70                 WSAWaitForMultipleEvents(1, &hEventArr[i], TRUE, 0, FALSE);
     71             if((sigEventIdx==WSA_WAIT_FAILED || sigEventIdx==WSA_WAIT_TIMEOUT))
     72             {
     73                 continue;
     74             }
     75             else
     76             {    /* 确定与hSockArr[sigEventIdx]套接字句柄相连接的事件对象hEventArr[sigEventIdx]转变为signaled状态的原因,
     77                   * 发生的事件类型信息和错误信息保存在netEvents结构体变量中
     78                   */
     79                 sigEventIdx=i;
     80                 WSAEnumNetworkEvents(
     81                     hSockArr[sigEventIdx], hEventArr[sigEventIdx], &netEvents);
     82                 if(netEvents.lNetworkEvents & FD_ACCEPT)
     83                 {    /* 发生连接请求事件 */
     84                     if(netEvents.iErrorCode[FD_ACCEPT_BIT]!=0)
     85                     {
     86                         puts("Accept Error");
     87                         break;
     88                     }
     89                     /* 接受连接请求 */
     90                     clntAdrLen=sizeof(clntAdr);
     91                     hClntSock=accept(
     92                         hSockArr[sigEventIdx], (SOCKADDR*)&clntAdr, &clntAdrLen);
     93                     /* 指定hClntSock套接字句柄为newEvent的监视对象,希望监视的事件类型为: 有需要接收的数据和断开连接请求 */
     94                     newEvent=WSACreateEvent();
     95                     WSAEventSelect(hClntSock, newEvent, FD_READ|FD_CLOSE);
     96 
     97                     hEventArr[numOfClntSock]=newEvent;
     98                     hSockArr[numOfClntSock]=hClntSock;
     99                     numOfClntSock++;
    100                     puts("connected new client...");
    101                 }
    102 
    103                 if(netEvents.lNetworkEvents & FD_READ)
    104                 {    /* 发生有需要接收的数据事件 */
    105                     if(netEvents.iErrorCode[FD_READ_BIT]!=0)
    106                     {
    107                         puts("Read Error");
    108                         break;
    109                     }
    110                     strLen=recv(hSockArr[sigEventIdx], msg, sizeof(msg), 0);
    111                     send(hSockArr[sigEventIdx], msg, strLen, 0);
    112                 }
    113 
    114                 if(netEvents.lNetworkEvents & FD_CLOSE)
    115                 {
    116                     if(netEvents.iErrorCode[FD_CLOSE_BIT]!=0)    
    117                     {
    118                         puts("Close Error");
    119                         break;
    120                     }
    121                     WSACloseEvent(hEventArr[sigEventIdx]);
    122                     closesocket(hSockArr[sigEventIdx]);
    123                     
    124                     numOfClntSock--;
    125                     CompressSockets(hSockArr, sigEventIdx, numOfClntSock);
    126                     CompressEvents(hEventArr, sigEventIdx, numOfClntSock);
    127                 }
    128             }
    129         }
    130     }
    131     WSACleanup();
    132     return 0;
    133 }
    134 
    135 void CompressSockets(SOCKET hSockArr[], int idx, int total)
    136 {
    137     int i;
    138     for(i=idx; i<total; i++)
    139         hSockArr[i]=hSockArr[i+1];
    140 }
    141 void CompressEvents(WSAEVENT hEventArr[], int idx, int total)
    142 {
    143     int i;
    144     for(i=idx; i<total; i++)
    145         hEventArr[i]=hEventArr[i+1];
    146 }
    147 void ErrorHandling(char *msg)
    148 {    
    149     fputs(msg, stderr);
    150     fputc('
    ', stderr);
    151     exit(1);
    152 }

    2.回声客户端实现

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <winsock2.h>
     5 
     6 #define BUF_SIZE 1024
     7 void ErrorHandling(char *message);
     8 
     9 int main(int argc, char *argv[])
    10 {
    11     WSADATA wsaData;
    12     SOCKET hSocket;
    13     char message[BUF_SIZE];
    14     int strLen;
    15     SOCKADDR_IN servAdr;
    16 
    17     if(argc!=3) {
    18         printf("Usage : %s <IP> <port>
    ", argv[0]);
    19         exit(1);
    20     }
    21 
    22     if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0)
    23         ErrorHandling("WSAStartup() error!"); 
    24 
    25     hSocket=socket(PF_INET, SOCK_STREAM, 0);   
    26     if(hSocket==INVALID_SOCKET)
    27         ErrorHandling("socket() error");
    28     
    29     memset(&servAdr, 0, sizeof(servAdr));
    30     servAdr.sin_family=AF_INET;
    31     servAdr.sin_addr.s_addr=inet_addr(argv[1]);
    32     servAdr.sin_port=htons(atoi(argv[2]));
    33     
    34     if(connect(hSocket, (SOCKADDR*)&servAdr, sizeof(servAdr))==SOCKET_ERROR)
    35         ErrorHandling("connect() error!");
    36     else
    37         puts("Connected...........");
    38     
    39     while(1) 
    40     {
    41         fputs("Input message(Q to quit): ", stdout);
    42         fgets(message, BUF_SIZE, stdin);
    43         
    44         if(!strcmp(message,"q
    ") || !strcmp(message,"Q
    "))
    45             break;
    46 
    47         send(hSocket, message, strlen(message), 0);
    48         strLen=recv(hSocket, message, BUF_SIZE-1, 0);
    49         message[strLen]=0;
    50         printf("Message from server: %s", message);
    51     }
    52     
    53     closesocket(hSocket);
    54     WSACleanup();
    55     return 0;
    56 }
    57 
    58 void ErrorHandling(char *message)
    59 {
    60     fputs(message, stderr);
    61     fputc('
    ', stderr);
    62     exit(1);
    63 }
  • 相关阅读:
    排序——字符串怀疑人生
    广搜的变形+最短路思想 变色龙
    阿斯顿发发顺丰
    莫队暴力 一知半解
    P3384 【模板】树链剖分
    U74201 旅行计划 树上找链长度
    数据结构:线性表基本操作和简单程序
    数据结构:循环链表实现约瑟夫环
    Codeforces 215D. Hot Days(贪心)
    Codeforces 1080C- Masha and two friends
  • 原文地址:https://www.cnblogs.com/chenweilin/p/12866397.html
Copyright © 2020-2023  润新知