套接字同时发送/接收
问题描述:
任何一个可以指出为什么我不能同时在套接字上发送和接收?套接字同时发送/接收
我的理解有2流的一个推,一个拉
,如果你尝试发送/同时接收你会得到wasealready错误
是什么原因,该插座抛出wasealready错误( 10035) 它与接收方发回的确认窗口有什么关系? 好像要保持该窗口的线条开放?
答
首先,我认为你对你的错误代码感到困惑。以下是几个可能相关的代码:
- WSAEALREADY(10037) - 您尝试发出已在进行中的请求。例如,试图
connect()
与已经在连接中的套接字。 - WSAEINPROGRESS(10036) - 即使跨多个线程,您也试图立即发出多个阻塞操作。
- WSAEWOULDBLOCK(10035) - 当套接字处于非阻塞模式时,您尝试进行阻塞的调用(例如,当没有数据可用时,recv)。
阻止你做两个阻塞操作一次的主要因素是WSAEINPROGRESS
错误 - 在Winsock 1.1的API的限制,只允许你做一个阻塞操作一次。您可以通过使用非阻塞重叠调用和Winsock 2.0 API来模拟阻塞调用。例如:
SOCKET sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
WSAEVENT hEvent = WSACreateEvent();
WSAEventSelect(sock, hEvent, FD_CONNECT); // register for connect notification
long iMode=1;
ioctlsocket(sock,FIONBIO,&iMode); // set non-blocking mode
WSAConnect(sock, address, sizeof(address), NULL, NULL, NULL, NULL);
WSAWaitForMultipleEvents(1, &events, FALSE, INFINITE, FALSE);
WSANETWORKEVENTS connect_result;
WSAEnumNetworkEvents(sock, hEvent, &connect_result);
if (connect_result.iErrorCode[FD_CONNECT] != 0) {
// connect failed, do something about it
}
WSACloseEvent(hEvent);
iMode = 0;
ioctlsocket(sock,FIONBIO,&iMode); // clear non-blocking mode; it won't play well with overlapped IO below
// Start an overlapped send
char *my_data = "Hello, world!";
WSAOVERLAPPED send_overlapped;
WSABUF send_buf;
send_buf.len = strlen(my_data);
send_buf.buf = my_data;
send_overlapped.hEvent = WSACreateEvent();
DWORD bytesSent;
WSASend(sock, &send_buf, 1, &bytesSent, 0, &send_overlapped, NULL);
if (WSAGetLastError() != WSA_IO_PENDING) {
// something went wrong, handle the error...
}
// Start an overlapped receive
char rdata[256];
WSAOVERLAPPED recv_overlapped;
WSABUF recv_buf;
recv_buf.len = sizeof(rdata);
recv_buf.buf = rdata;
recv_overlapped.hEvent = WSACreateEvent();
DWORD bytesRecvd;
WSARecv(sock, &recv_buf, 1, &bytesRecvd, NULL, &recv_overlapped, NULL);
if (WSAGetLastError() != WSA_IO_PENDING) {
// something went wrong, handle the error...
}
// Now wait for both to finish
WSAEVENT events[2];
events[0] = recv_buf.hEvent;
events[1] = send_buf.hEvent;
WSAWaitForMultipleEvents(2, events, TRUE, INFINITE, TRUE);
这种方法有点复杂,但非常灵活 - 一旦你火了一个重叠I/O的工作,同样的线程可以继续做其他工作(只要你保持缓冲区和什么没有分配!)。需要注意的一件事是,如果你在GUI线程上执行此操作,则需要更改消息循环 - 为了完成重叠事件,发布它们的线程需要执行可警告等待,例如使用MsgWaitForMultipleEvents
。在上面的示例中,我使用WSAWaitForMultipleEvents
来执行此可警告等待。此外,发出重叠I/O请求的线程在请求完成之前不得终止。
对于重叠I/O,看到这个MSDN页面上的一般信息:http://msdn.microsoft.com/en-us/library/ms686358(v=vs.85).aspx
10035是WSAEWOULDBLOCK,有你把你的窝在非阻塞模式? – nos 2011-02-11 15:38:46