系统是这样的, 因为要建立大量的socket, 所以在一个时间内需要大量的connect
做法 有2
 1  多线程 使用阻塞模式进行 connect. 当connect 成功以后, 将socket 加入iocp 进行操作   缺点  比如 当远端网络出现问题, syn发送后 一直没有相应的时候, connect 会被阻塞住, 在 75 秒以内都是不会返回的。效率会很低。所以我使用了下面的方法
2  connect 使用非阻塞模式,  然后 直接将socket 加入 iocp,  进行相应的读写 投递。为代码 如下
#ifdef WIN32
unsigned long ul = 1;
int ret = 0;
ret = ioctlsocket(sClient, FIONBIO, (unsigned long*)&ul);if(ret==SOCKET_ERROR) return false;#endif
// 进行connect
 result = connect( Prequest->GetSocket(), (struct sockaddr *)&clientadd, sizeof(clientadd));
 
    if (result == SOCKET_ERROR)
     {
        if (WSAGetLastError () ==  WSAEWOULDBLOCK)
        {
            
        } else
        {
 
        }
    }
   
此时 connect 会得到一个 WSAEWOULDBLOCK 错误如果网络此时已经联通  比如在本地的服务。那么随后 我进行 一次 iocp 的读投递 和 写投递都能在  另一个线程的        if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
            (LPDWORD)&PerHandleData, (LPOVERLAPPED *)&PerIoData, 1*1000) == 0)中获得 消息。
但是如果 假设 我使用了
arp -s xx.xxx.xxx.xx 11-11-11-11-11这样的方法 进行网络欺骗, 那么 此时端口处于 send syn 的状态而我进行读和写投递的时候// 为代码
if (WSARecv(pnewdata->m_socket, &(pnewdata->DataBuf), 1, &RecvBytes, &                            Flags,
                        &(pnewdata->Overlapped), NULL) == SOCKET_ERROR)
                    {
                        if (WSAGetLastError() != ERROR_IO_PENDING)
                        {
                         printf("WSARecv() failed with error %d\n", WSAGetLastError());
                        return;
                        }
                    }这个时候 就会出现 错误 WSAENOTCONN因为此时还没有建立起连接 难道 connection 不成功, 我就没办法了吗?
我理想的情况是 connection 不成功, 但是投递应该能完成,只是不返回,当超时的时候到达, 他们通过GetQueuedCompletionStatus 返回出来,告诉我 read 或者 write = 0  我好进行逻辑处理。
或者说如果connection 成功的时候, 我能获得什么消息吗?select 方案 我已经放弃了 谢谢!因为已经在linux 下面同样的实现了一套 网络层,所以现在正在iocp 中实现类似的协议层
请高手帮忙!!!

解决方案 »

  1.   

    往完成端口投递IO操作,必须使用支持重叠IO的函数,标志就是需要使用overlapped参数
    否则不会触发GetQueuedCompletionStatusconnect函数不支持重叠IO,而且,WSAConnect好像也不支持
    ConnectEx倒是含overlapped参数的,不过偶也没用过往IOCP投递ConnectEx,你可以试试看
      

  2.   


    The ConnectEx function establishes a connection to a specified socket, and optionally sends data once the connection is established. The ConnectEx function is only supported on connection-oriented sockets.
      

  3.   

    你在Linux下实现的是用的什么的?Linux下应该没有iocp的吧。
      

  4.   

    linux 下面epollconnect  以后 靠epoll 检查,在syn 发出75 秒 没有相应的情况下, epoll 会返回 可以read 但是read == 0 那么我就知道 连接断开了, 实质 是 根本没connect 成功,对逻辑上没影响
      

  5.   

    IOCP的socket必须是阻塞模式的,可以非阻塞connect,连接成功后改回阻塞模式,以前有人提到过这个问题
    http://topic.csdn.net/u/20090212/14/1880e581-f7fe-4078-baad-9110f40d363c.html那个贴子2#的回复..
    那就是因为他觉得阻塞用着收发爽,但是connect超时太久不爽。
      

  6.   

    好像检测非阻塞的需要select,如果可写了,就说明连通了
    如果不喜欢select,用WSAEventSelect也行,也要wait FD_WRITE网络事件不过一般都是server端用iocp,客户端用的比较少
      

  7.   

    上面写错了,应该是wait FD_CONNECT事件
    具体看WSAEventSelect吧
      

  8.   

    如果这样的话 我的network 模块的模型 设计就有问题了,,iocp 原来我都是阻塞connect的,当遇到多个连接的话 效率实在不高。我设计的模型 network 都是快速的回复, 比如connect 以后, 在以后的某一时间 告诉我失败或者成功。send recv 都是这样, 如果按照你们所说的 那么 需要select 来处理, 有2个缺点 第一 同一时间 可以发起的连接数目 受到 select 影响。第二 在select 工作 同时 io 模块不能处理新的 连接请求 (主动连接) 实在不怎么好。
      

  9.   

    没做过这块,希望LZ解决问题后把思路共享下....有个connectEX貌似IOCP可以用可以用WSAEventSelect或WSAAsyncSelect替代Select,没有连接限制..