• WSAEventSelect IO复用模型


    1 今天帮一学习WSAEventSelect的网友排查一个测试用服务器端recv返回0的问题,出现这个问题直观判断一般是客户端socket关闭了,可是他的代码很简单并且是本机测试,通过wireshark抓包也没有发现客户端发送了FIN分节,错误码为0,一切看起来都是正常的。正当无思路时,突然想到会不会是将recv的缓冲区长度参数给设置为0了呢,后发现果然如此,代码如下:

        else if(event.lNetworkEvents & FD_READ)   // 处理FD_READ通知消息  
        {  
         if(event.iErrorCode[FD_READ_BIT] == 0)  
         {  
          char szText[256];  
          int nRecv = ::recv(sockArray[i], szText, strlen(szText), 0);  
          if(nRecv > 0)      
          {  
           szText[nRecv] = '';  
           printf("接收到数据:%s 
    ", szText);  
          }  
         }  

    szText是栈的一个没有初始化的字符数组,strlen(szText)返回值就有很大随机性了,这里要改为sizeof(szText)-1

    2 WSAEventSelect模型最多复用64个socket,这个说法是片面的,这是由于将每一个socket描述符对应一个事件句柄,从而达到了WSAWaitForMultipleEvents这个函数所要求的等待事件的上限造成的,实际中也可以通过WSAEventSelect调用将多个socket关联到一个事件句柄上,WSAWaitForMultipleEvents只等待一件事件即可,这样可以复用多于64个socket

    3 在用WSAEnumNetworkEvents返回的event的lNetworkEvents与FD_xxxx相与判断相应事件时不应该if...else if...else if,要if ...  if ... if ...,因为有时候一个socket会返回多个事件

    4 WSAEventSelect模型时如何发送数据,首先创建socket(服务器端通过accept) fd,然后调用ioctlsocket这个将fd设为非阻塞模式,接下来调用WSAEventSelect将该fd同一个事件event相关联,关联事件属性之一为FD_WRITE,这样在接下来通过WSAWaitForMultipleEvents等待前述event时或直接调用WSAEnumNetworkEvents,一定会有第一个FD_WRITE事件可用,此时若有数据可写可在此事件中写,若无可跳过,接下来在收到FD_CLOSE事件之前都是可以直接send数据并判断返回值,若返回值为-1且错误码为WSAEWOULDBLOCK,说明低层socket发送缓存区满了,此时应用程序要记忆已发送位置,并在下一个FD_WRITE事件到来时继续发送余下的或更新的数据

  • 相关阅读:
    第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京)K Co-prime Permutation
    2020 CCPC绵阳站赛后回忆+总结
    CF 1473D Program
    Educational Codeforces Round 100 (Rated for Div. 2) 补题情况
    Codeforces Round #690 (Div. 3) (补题情况)
    这个博客停用,新博客地址:www.baccano.fun
    炫酷路径(牛客)
    洛谷 P1123 取数游戏
    洛谷P2802 回家
    cf上分的失落->高兴->更失落
  • 原文地址:https://www.cnblogs.com/oldmanlv/p/5731337.html
Copyright © 2020-2023  润新知