2009-09-02 8 views
0

Windows 소켓에서 WSAEventSelect I/O 모델을 사용하고 있으며 이제는 보내기 및 받기 작업이 모든 데이터를 보내고 받았음을 어떻게 알 수 있습니까?Winsocks 보내기 및 받기

내가 알기도하면 데이터를 완전히 전송할 수 있도록 어떻게 디자인해야합니까? 모든 예제는 정말 감사하겠습니다. 여기

코드 (I로부터 배우고 책의 샘플 코드)입니다 : 나는이 메시지 것 (완료받을 수 있는지 결정하기 위해 부울 플래그를 설정 것이라고 생각 무엇

SOCKET SocketArray [WSA_MAXIMUM_WAIT_EVENTS]; 
WSAEVENT EventArray [WSA_MAXIMUM_WAIT_EVENTS], 
NewEvent; 
SOCKADDR_IN InternetAddr; 
SOCKET Accept, Listen; 
DWORD EventTotal = 0; 
DWORD Index, i; 
WSANETWORKEVENTS NetworkEvents; 


// Set up socket for listening etc... 
// .... 

NewEvent = WSACreateEvent(); 

WSAEventSelect(Listen, NewEvent, 
       FD_ACCEPT │ FD_CLOSE); 

listen(Listen, 5); 

SocketArray[EventTotal] = Listen; 
EventArray[EventTotal] = NewEvent; 
EventTotal++; 

while(TRUE) 
{ 
    // Wait for network events on all sockets 
    Index = WSAWaitForMultipleEvents(EventTotal, 
     EventArray, FALSE, WSA_INFINITE, FALSE); 
    Index = Index - WSA_WAIT_EVENT_0; 

    // Iterate through all events to see if more than one is signaled 
    for(i=Index; i < EventTotal ;i++ 
    { 
     Index = WSAWaitForMultipleEvents(1, &EventArray[i], TRUE, 1000, 
      FALSE); 
     if ((Index == WSA_WAIT_FAILED) ││ (Index == WSA_WAIT_TIMEOUT)) 
      continue; 
     else 
     { 
      Index = i; 
      WSAEnumNetworkEvents(
       SocketArray[Index], 
       EventArray[Index], 
       &NetworkEvents); 

      // Check for FD_ACCEPT messages  
      if (NetworkEvents.lNetworkEvents & FD_ACCEPT) 
      { 
       if (NetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0) 
       { 
        printf("FD_ACCEPT failed with error %d\n", 
         NetworkEvents.iErrorCode[FD_ACCEPT_BIT]); 
        break; 
       } 

       // Accept a new connection, and add it to the 
       // socket and event lists 
       Accept = accept(
        SocketArray[Index], 
        NULL, NULL); 

       NewEvent = WSACreateEvent(); 

       WSAEventSelect(Accept, NewEvent, 
        FD_READ │ FD_CLOSE); 

       EventArray[EventTotal] = NewEvent; 
       SocketArray[EventTotal] = Accept; 
       EventTotal++; 
       printf("Socket %d connected\n", Accept); 
      } 

      // Process FD_READ notification 
      if (NetworkEvents.lNetworkEvents & FD_READ) 
      { 
       if (NetworkEvents.iErrorCode[FD_READ_BIT] != 0) 
       { 
        printf("FD_READ failed with error %d\n", 
         NetworkEvents.iErrorCode[FD_READ_BIT]); 
        break; 
       } 

       // Read data from the socket 
       recv(SocketArray[Index - WSA_WAIT_EVENT_0], 
        buffer, sizeof(buffer), 0); 

       // here I do some processing on the data received 
       DoSomething(buffer); 

       // now I want to send data 
       send(SocketArray[Index - WSA_WAIT_EVENT_0], 
         buffer, sizeof(buffer), 0); 
       // how can I be assured that the data is sent completely 

      } 

      // FD_CLOSE handling here 
      // ...... 
      // ...... 
     } 
    } 
} 

길이를 접두어로 한 다음 해당 데이터 처리를 시작합니다. 하지만 은()을 보내시겠습니까? 가능성을 말해 주시겠습니까?

** 편집 : 당신이 취급하고있는 프로토콜 (애플리케이션 계층)은 당신이받을 수에 대한있어 얼마나 많은 데이터에 대한 정보를 제공하지 않는 한 ** FD_READ 이벤트 부분

답변

0

를 참조 유일한 방법은 있는지 확인하기 피어가 연결을 끊을 때 더받을 것이 없습니다. 서버가 단순히 전송을 멈추는 경우, 서버가 끝나거나 그냥 사용 중인지 확인할 수 없습니다. 끝나면 끝납니다. 또한 서버가 종료되었거나 연결이 끊어져 서버 연결이 끊어 졌는지 여부를 판별 할 수 없습니다.

대부분의 프로토콜이 송신하기 전에 송신 될 바이트 수를 피어에게 알려주거나 데이터의 끝 부분에 경계를 배치하는 이유는 무엇입니까?

전송에 관해서는 사용중인 버퍼를 알고 있어야합니다. send() 때, 버퍼로 이동합니다 (기본적으로 64KB). send()은 버퍼에있는 바이트 수를 반환합니다. 전송하려는 바이트보다 적 으면 FD_WRITE 이벤트를 수신 할 때 다시 시도하도록 관리해야합니다.

mIRC DDC가 정보를 제공하지 않는 한 상대방이 이미 수신 한 데이터의 양에 대해 확신 할 수 없습니다.

는 의심을 clearfyed 확실하지, 당신은 데이터가 수신되었는지 확인하기 위해 반환 상태를 저장해야합니다, 당신은 RECV을 수행하는 경우가

+0

문제는 내부 버퍼가 가득 차서 FD_WRITE 이벤트를 다시 전송할만큼 충분한 데이터를 보내야하기 때문에 FD_WRITE 이벤트를 기다리는 것이 아닙니다. 내가하고있는 일은 비동기식으로 보내는 것이지만 데이터가 성공적으로 전송되었음을 알 필요가있다. 어떻게해야합니까? – akif

+0

간단하다. FD_WRITE를 기다린다. – Havenard

+0

짧은 메시지 (1, 2 바이트)를 보내고 있기 때문에 내부 버퍼가 꽉 찼다면 다른 FD_WRITE 이벤트를 얻지 못할 것이다. – akif

0

:) 도움이되기를 바랍니다. recv는받은 바이트 수를 반환하고, 네 번째 매개 변수에 대해 0 대신 플래그 MSG_WAITALL을 사용하여 모든 메시지를 수신합니다 (버퍼 크기를 기반으로 함). 상태 recv 반환 값이 음수이면 연결이 상대방과 가까워 지거나 다른 문제가있는 것처럼 몇 가지 성질의 오류가있었습니다.

send의 경우 반환 값을 상태로 저장해야하지만이 경우 반환하기 전에 모든 데이터를 보낼 플래그가 없습니다. 전송량을 결정하고 버퍼를 조정하고 값에 따라 크기를 전송해야합니다. recv와 마찬가지로 음수 값은 오류가 발생했음을 나타냅니다.

반환 값 및 플래그에 대한 자세한 내용은 Microsoft 웹 사이트 recvsend에 대한 기능 설명을 읽습니다.

+0

MSG_WAITALL은 SOCK_DGRAM (UDP 및 RAW) 용입니다. SOCK_STREAM (TCP)이 중단됩니다. – Havenard

관련 문제