2011-09-10 3 views
2

Winsock2 래퍼 클래스 (클라이언트 - 서버)에 문제가 있고 혼란에 빠져있는 수많은 시간 후에 혼란 스러웠습니다. 당신의 의견.C++, Send() 함수가 여분의 바이트를 보냅니다.

더 구체적으로 말하자면, 문제는 클라이언트 (항상)가 ​​아닌 Send() 함수를 사용할 때마다 하나 또는 두 개의 추가 바이트가 전송된다는 것입니다.

예를 들어 SendBytes ("Hello")를 사용하고 Recv 함수는 문자 배열 끝에 '•'또는 다른 임의의 문자가있는 "Hello?"를 반환합니다. 물론

//main.cpp (Client) 
    #include "Socket.h" 

    int main() 
    { 
     NetworkService::Client cService = NetworkService::Client(); 
     int res = cService.Initialize("127.0.0.1","20248"); 
     if(res == 0){ 
      int local = cService.SendBytes("Hello!"); 
      printf("Bytes Sent: %ld\n", local); 
      cService.Shutdown(); 

      char* temp = cService.Recv(); 
      printf("String Recieved: %s - Size: %d",temp,strlen(temp)); 
      printf("\nSTRLEN: %d",strlen("X5")); 
     } 
     else{ 
      cService.Clean(); 
     } 
     cService.Close(); 
     while(!kbhit()); 
     return 0; 
    } 

, 서버는 "X5"문자열을 전송하고 클라이언트는 strlens을 인쇄 ...

//The result with "X5" as the dummy text: 
String Recieved: X5? - Size: 3 //Notice the extra '?' character 
STRLEN: 2 

보내기 // 받으십시오 기능

int NetworkService::Client::SendBytes(char* lData){ 
      int local = send(ConnectSocket, lData, (int)strlen(lData), 0); 
      if (local == SOCKET_ERROR) { 
       Close(); 
       return WSAGetLastError(); 
      } 
      return local; 
    } 

    char* NetworkService::Client::Recv(){ 
     recv(ConnectSocket, recvbuf , recvbuflen, 0); 
     return recvbuf; 
    } 

도움을 주시면 감사하겠습니다^_ ^.

+2

문자열에 종료 NUL 바이트를 보내지 않습니다. –

+0

너무 빨리 답변 해 주셔서 감사합니다! Heres, 나는 문자열 끝에 '\ 0'을 추가했으나 아무것도하지 않았다. 나는 여전히 무작위 삽입을 얻는다. – Christian

+1

@christian : 문자열 리터럴을 통해 암시적인 \ 0을 이미 갖고 있습니다. 그것을 보내기 위해서는 send() 호출에서 size 매개 변수를 조정해야합니다. strlen (lData)에서 strlen (lData) +1로 변경하여 후행 \ 0을 포함시킵니다. 왜 이것이 필요한지 확실하지 않다면 [strlen()] (http://cplusplus.com/reference/clibrary/cstring/strlen/) 함수를 찾아보십시오. – ComicSansMS

답변

1

정말로recv의 반환 값을 확인하십시오.

do-while은 있지만 아무 것도하지 않습니다. recv이 실패하더라도 적절한 오류 처리 기능없이 함수에서 복귀하지만 결코 알 수 없습니다.

또한 당신이하지 말아야 할 종단을 보내지 말고, 당신이 무엇을하려고하는지에 따라 다릅니다. 예를 들어 수신 후에 추가 할 수 있습니다.

+0

\ 0을 추가하려고했지만 아무 것도하지 않았습니다. 문자열 끝에 임의의 문자가 삽입됩니다. 그렇다면 질문은 여전히 ​​삽입의 원인이 무엇입니까? recv 노트 주셔서 감사합니다, 나는 항상 recv 때마다 버퍼에 다른 바이트를 추가한다고 생각합니다. 반환 값은 1 씩 증가합니다. – Christian

+0

잘 처리하는 방법에 대해 이야기했습니다. –

+0

좋아, 나는 그것이 고정 된 것 같아요. 나는 당신에게 그것을위한 크레딧을 줄 것이다 ^^. – Christian

3

실례합니다,하지만

int local; 
(...) 
return (int*)local; 

당신이 달성하려고했다? 코드에는 많은 심각한 문제가 있습니다.

+0

RecvBytes가 int *이고 Recv가 int를 리턴하기 때문에 경고/오류가 발생합니다. – Christian

+1

이해가 안됩니다. 당신은 의미가없는 정수로부터 포인터를 만들고 있습니다. 내 경고가 segfaulting을 의미 했습니까? 글쎄, 훨씬 더 명확한 생각은 예외를 던지는 것이다. – Nyton

2

이것은 네트워크를 통해 데이터를 보내는 방식이 아닙니다. 너무 많은 오류가 있습니다.

네트워크를 통해 null로 끝나는 문자열을 보낼 경우 : 모든 사람이 말했듯이

int local = send(ConnectSocket, lData, (int)strlen(lData), 0); 

, 당신은 실제로 null 종결를 전송하지 않습니다. 길이에 1을 더하면 그것을 보냈을 것입니다. 또한 긴 문자열의 경우 send() 함수가 전체 문자열을 한 번에 보낼 수 있다고 보장하지 않습니다. 그것을 확인하고 누락 된 부분을 다시 보내야합니다.

recv(ConnectSocket, recvbuf , recvbuflen, 0); 

반환 값을 확인하지 않으므로 수신 한 문자열의 길이를 알 수 없습니다. 널 바이트를 전송하지 않으므로 수신 된 데이터는 널로 종료되지 않습니다. 또한 널 터미네이터가 전송하는 더 많은 데이터를 구분하는 유일한 구분자 인 경우, 널 종료자를 놓치지 않고 바이트 단위로 읽어야 만 (효율적인 것은 아닙니다) 언제 완료해야하는지 알 수 있습니다. 대안으로는 독자적인 버퍼링 체계를 만들 수 있습니다 (다음 읽기는 이전 결과를 부분적으로 반환합니다). 또는 프로토콜을 변경하여 전송 된 데이터의 길이를 미리 알 수 있도록합니다. 또한 여기서는 send 함수와 같은 부분 읽기에 대한 동일한 설명이 적용됩니다.

정적/전역 버퍼를 반환하는 것은 좋은 코드의 표시가 아닙니다.

+0

알았어, 음, 우선 내가 그걸 돌려 준다고? Recv는 들어오는 데이터를 버퍼에 복사하므로 완료되면 buffer.Look을 반환합니다. 데이터를 한 번 보내는 것은 오류가 발생하기 쉽기 때문에 두 번 보내고 클라이언트의 결과를 비교해야합니다. 나는 그것도 시도했지만, 내가 원하는 결과를 보장하지는 않는다. 패킷은 그대로 나오고 그대로 간다. BTW 이것은 마이크로 소프트 코드입니다, 나는 단지 클래스의 모든 것을 래핑합니다. :) – Christian

+0

사실 길이를 1 씩 늘리고 NUL 터미네이터를 보내면 트릭을했습니다! 처음 알게 된 Steve-o에게 감사드립니다! 그리고 당신의 팁을위한 다른 모든 사람들 !! – Christian

+1

@Christian 코드가 "작동하지 않음"에서 "작동 함"으로 변경되었습니다. 'recv'의 반환 값을 무시하고 C 스타일의 문자열이 될 수없는 C 스타일의 문자열 데이터로 취급하기 때문에 여전히 엄청난 파손 상태입니다. –

관련 문제