2011-02-11 14 views
0

한 번에 소켓에서 보내고받을 수없는 이유를 지적 할 수 있습니까? 나의 이해에소켓 동시에 보내기/받기

당신이 보내려고하면

당겨 2 개 밀어 스트림 하나 하나가/당신이 (소켓 wasealready 오류가 발생하는 이유는 무엇 wasealready 오류

을 얻을 것이다 동시에받을 10035) 수신 측에서 보낸 확인 창과 관련이 있습니까? 마치 창문에 대해 열어 두는 것처럼?

+0

10035이 WSAEWOULDBLOCK입니다, 당신은 블로킹 모드에서 소켓을 넣어 있나요? – nos

답변

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