2012-10-06 2 views
2

내 서버는 500kb 크기의 이미지 두 개를 클라이언트에 보내야합니다. 클라이언트는 아무런 데이터 손실없이 첫 번째 이미지 벌금을 받지만 서버가 다른 이미지를 클라이언트에 보냈을 때 recv()는 서버에서 데이터를 보내기 전에 0을 반환하고 서버 바로 다음에 send()는 -1을 반환합니다 .소켓이 큰 데이터를받은 후 recv()가 0을 반환합니다.

가 여기 내 전송()이며 RECV() 코드 :

서버 :

fp2 = fopen(totaldir2,"rb"); 
if(fp1==NULL) 
{ 
    cout<<"ERROR while openning: "<<totaldir2<<endl; 
    getchar(); 
    exit(1); 
} 

fseek (fp2, 0 , SEEK_END); 
IFileSize2 = ftell (fp2); 
rewind (fp2); 
picture2 = new char[sizeof(char)*IFileSize2+1]; 
if (picture2 == NULL) {exit (2);} 
itoa (IFileSize2,CFileSize2,10); 
countData = 0; 
do{ 
sentData = send(sConnect,CFileSize2,strlen(CFileSize2)+1,NULL); 
countData+=sentData; 
}while(countData<strlen(CFileSize2)+1); 
read = fread_s(picture2, IFileSize2, sizeof(char),IFileSize2, fp2); 
countData = 0; 
do{ 
sentData = send(sConnect, picture2, read, 0); 
countData += sentData ; 
}while(countData<read); 

이 코드는 두 개의 이미지를 전송 두 번 실행됩니다.

클라이언트 :

recv(sConnect, len2, sizeof(len2) ,NULL); \\recv returns 0 here before server sends the data. 
FileSize2 = atoi(len2); 
picture2 = new char[sizeof(char)*FileSize2+1]; 
fp2 = fopen("temp\\image2.bin","wb"); 
if(fp2==NULL) 
{ 
    closesocket(sConnect); 
    WSACleanup(); 
    exit(1); 
    } 

recv(sConnect, picture2, FileSize2, 0); \\same here 
fwrite(picture2, sizeof(char), Received2, fp2); 

이 코드는 두 개의 이미지를받을 두 번 실행됩니다.

서버에 send() 후에 Sleep()을 넣으면 클라이언트는 모든 데이터와 모든 이미지를 수신하지만 절전 모드는 클라이언트 네트워크에 따라 다릅니다. 그리고 서버는 많은 클라이언트를 얻습니다. 연결은 TCP와 함께 사용됩니다.

답변

1

recv()은 상대방의 정상적인 연결이 끊어지면 0을 반환합니다. TCP는 바이트 스트림이라는 것을 기억하십시오. UDP와 같은 메시지 개념이 없습니다. 대부분의 경우 두 번째 이미지는 recv()에 대한 첫 번째 호출에 사용중인 것과 동일한 버퍼에 저장됩니다. 파일 데이터를 보내기 전에 파일의 길이를 보내는 것과 같이 데이터 프레임을 만들어야합니다. 그런 식으로, 수신기는 길이를 먼저 읽을 수 있고 그 다음 길이만큼 읽습니다. 당신은 그것을하려하지만, 당신은 그것을 잘 관리하지 못하고 있습니다. 우선, 가변 길이 문자열을 사용하여 파일 길이를 보냅니다. 이것은 문자열 길이를 전송하지 않고 수신자가 널 종결자를 찾지 않아 수신자가 문자열의 길이를 알지 못하고 너무 많은 바이트를 읽지 않기 때문에 좋은 생각이 아닙니다. 파일 길이를 고정 길이 4 바이트 int 또는 8 바이트 __int64 대신 보내야합니다. 그것은 수신기가 읽기가 훨씬 쉬울 것입니다.

+0

파일 길이를 int로 보내려면 어떻게해야합니까? – eilonmore

+0

이렇게 :'int filesize = ...; send (sConnect, (char *) & filesize, sizeof (int), 0);를 호출 한 다음 수신 측에서 : int filesize; recv (sConnect, (char *) & 파일 크기, sizeof (int), 0);'. 이것은 블로킹 소켓을 가정합니다. non-blocking 소켓을 사용한다면'EAGAIN' /'EWOULDBLOCK' 에러를 설명하기 위해이 로직을 조정해야하지만 핵심 개념은 여전히 ​​적용됩니다. –

관련 문제