2011-02-11 245 views
0

任何一個可以指出爲什麼我不能同時在套接字上發送和接收?套接字同時發送/接收

我的理解有2流的一個推,一個拉

,如果你嘗試發送/同時接收你會得到wasealready錯誤

是什麼原因,該插座拋出wasealready錯誤( 10035) 它與接收方發回的確認窗口有什麼關係? 好像要保持該窗口的線條開放?

+0

10035是WSAEWOULDBLOCK,有你把你的窩在非阻塞模式? – nos 2011-02-11 15:38:46

回答

2

首先,我認爲你對你的錯誤代碼感到困惑。以下是幾個可能相關的代碼:

  • 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

相關問題