zoukankan      html  css  js  c++  java
  • 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事件到来时继续发送余下的或更新的数据

  • 相关阅读:
    实现实体类和Xml相互转化
    创建型设计模式之原型模式(Prototype)
    创建型设计模式之建造者模式(Builder)
    行为型设计模式之状态模式(State)
    行为型设计模式之职责链模式(Chain of Responsibility)
    行为型设计模式之解释器模式(Interpreter)
    行为型设计模式之模板方法(Template Method)
    结构型设计模式之享元模式(Flyweight)
    结构型设计模式之外观模式(Facade)
    获取必应壁纸
  • 原文地址:https://www.cnblogs.com/oldmanlv/p/5731337.html
Copyright © 2011-2022 走看看