系统是这样的, 因为要建立大量的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 中实现类似的协议层
请高手帮忙!!!
做法 有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 中实现类似的协议层
请高手帮忙!!!
否则不会触发GetQueuedCompletionStatusconnect函数不支持重叠IO,而且,WSAConnect好像也不支持
ConnectEx倒是含overlapped参数的,不过偶也没用过往IOCP投递ConnectEx,你可以试试看
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.
http://topic.csdn.net/u/20090212/14/1880e581-f7fe-4078-baad-9110f40d363c.html那个贴子2#的回复..
那就是因为他觉得阻塞用着收发爽,但是connect超时太久不爽。
如果不喜欢select,用WSAEventSelect也行,也要wait FD_WRITE网络事件不过一般都是server端用iocp,客户端用的比较少
具体看WSAEventSelect吧