2013-07-15 3 views
0

아래 코드에 어떤 문제가 있습니다. 서버에서 파일을 수신하도록 설계되었습니다. 전송 후 서버 연결이 끊어지면 100 % 정상적으로 작동합니다.서버가 연결을 끊을 경우에만 파일 전송이 완료됩니다.

서버 연결이 끊어지지 않으면 전송이 클라이언트 측을 완료하지 않고 클라이언트는 바이트를 계속해서 보내고 fr_block_sz == 0 일 때 제대로 루프를 벗어나지 않습니다. 파일 수신 후 서버 연결이 끊어 질 때 수행됩니다. 그것은 끝없이 루프에 앉는다.

파일을 받고 나중에 연결을 유지하고 싶습니다. 어떤 충고? 감사.

EDIT : Casey의 조언 이제 아래 주석 코드를 통해 작성된 바이트 수를 모니터링하고 있지만 파일 전송이 제대로 완료되지 않는 이상한 동작이 나타납니다. 누구든지 내 코드에서 잘못된 일을 볼 수 있습니까? 감사.

편집 2 : 문제를 명확하게하려고 디버깅 정보를 게시했습니다.

// Reciever of file (client) 
int TotalSize = 7374; // hardcoded file size to expect 
int FileSize = 0; // counter 
int fr_block_sz = 0; 
while ((fr_block_sz = recv(sd, revbuf, 1, 0)) > 0) //LENGTH == 512 
{ 
    if (fr_block_sz < 0) 
     if (errno == EAGAIN) 
      continue; 
     else 
      printf("File write failed"); 

     if (fr_block_sz == 0)   
      break; //done 

     // edit based on comment - does not change behavior 
     if(FilzeSize > TotalSize) 
     { 
      fr_block_sz = fr_block_sz - (FileSize - TotalSize); 
     }    

     int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr); 
     // add total bytes recvd every loop 
     FileSize += write_sz; 
     // if bytes recieved equals expect file size, break 
     if (FileSize >= TotalSize)// this is where my problem is, as sometimes 
            // FileSize == 7376 or 7672 instead of 7374 
            // When it fails, fr_block_sz == 24 which 
            // i don't think is right either. Even when 
            // set to break if FileSize > TotalSize, the 
            // loop still doesn't complete 
      break; 
     printf("Recieved size == %i of %i \n", FilzeSize, TotalSize); 

     if (write_sz < fr_block_sz) 
     { 
      printf("File write failed"); 
     } 

     bzero(revbuf, 1); 

} 
printf("Transfer complete \n"); 

콘솔 출력 : 그것은 여기에 도착하면

Recieved size == 512 of 7374 
Recieved size == 1024 of 7374 
Recieved size == 1368 of 7374 
Recieved size == 1880 of 7374 
Recieved size == 2392 of 7374 
Recieved size == 2736 of 7374 
Recieved size == 3248 of 7374 
Recieved size == 3760 of 7374 
Recieved size == 4104 of 7374 
Recieved size == 4616 of 7374 
Recieved size == 5128 of 7374 
Recieved size == 5472 of 7374 
Recieved size == 5984 of 7374 
Recieved size == 6496 of 7374 
Recieved size == 6840 of 7374 
Recieved size == 7352 of 7374 
Recieved size == 7376 of 7374 

는, 클라이언트가 루프에 영원히 여기에 대기하고 아무 일도 발생하지 않습니다. 그런 다음 콘솔에서 프로그램을 수동으로 중지해야하고 프로그램이 중지 된 후 파일의 4096 바이트 만 기록됩니다. 나는 누군가가 내 문제에 대해 밝히거나,이를 위해 "정상적인"방법을 밝힐 수 있다면 가장 감사하게 생각한다. 고맙습니다.

EDIT - FIXED (일종의). 내가 안정적으로 100 % 작동 할 수있는 방법을 발견하고 길이 == 1로 변경하여 1 바이트 버퍼 크기를 설정하고, 커널이 바이트를 쓰고 있다면 짧은/긴 읽기를 얻을 수 없다. . 이 방법이 효과적이지만 가장 빠른 해결책은 아닙니다. 나는 여전히 다른 사람들의 이야기를 듣고 싶습니다. 당신의 도움에 감사드립니다. Rajal.

+0

그래서 당신은 서버 코드에서 볼 필요가 대신 – bbonev

+0

관련없는 : 다른 데이터로 채우기 전에 제로로 버퍼를 작성하는 것은 무의미하다. – Casey

+0

Casey - 고정, bbonev - 막연한 설명, 후속 조치. – 4r4r4r

답변

1

문제는 서버가 연결을 닫지 않으면 클라이언트가 파일 전송이 완료된시기를 알 수 없다는 것입니다. 그 사실을 어떻게 알릴 수 있니?

+0

나는 송신 후 확인 바이트를 보내기 위해 서버를 코딩하려고 시도했다. 서버가 연결이 끊긴 경우에만 작동하고 클라이언트가 파일 + 1 바이트 (확인)를 작성하고 루프 내의 특정 바이트와 비교하는 방법을 파악할 수 없습니다. 나는 서버가 바이트를 보낼 필요가 있다고 가정하고, 0xAA라고 말하자. 그러면 클라이언트가 루프에서 빠져 나올 수있는 바이트를 얻는다. – 4r4r4r

+0

그러나 파일 데이터에 0xAA가 있으면 어떻게됩니까? 'recv'의 데이터 덩어리는 보내진 것과 똑같은 방식으로 나누어 져야한다는 것을 믿을 수는 없습니다 : 당신은 순서가 보장되어 있지만 덩어리는 쪼개 지거나 병합 될 수 있습니다. – Casey

+0

힌트 : 서버가 데이터를 보내기 전에 클라이언트에 데이터 길이를 알려주도록하십시오. – Casey

1

클라이언트와 서버 간의 일부 프로토콜을 따르는 것이 좋습니다. 아래에 나와있는 예제를 볼 수 있습니다.

  1. 모든 통신의 처음 4 바이트가 파일 크기라고 가정하고 클라이언트에서 가정합니다. 첫 x 째 4Y이 트는 확립 된 연결마다 파일이 완전히 전송 될 때까지 서 v에서 전송합니다. 다른 파일/회의의 경우 서버는 파일 크기를 나타내는 4 바이트를 다시 보냅니다.
  2. 따라서 클라이언트의 처음 4 바이트는 처리해야하는 데이터의 양을 정확하게 나타냅니다.
  3. 클라이언트는 4 바이트를 정수로 변환하여 수신 할 정확한 바이트 수를 얻을 수 있도록 풀 버퍼로 가정하는 대신 처음에는 4 바이트 만 읽습니다. 확인 바이트는 필요 없으며 여기에있는 것은 쓸모가 없습니다.
  4. 일단 수신 된 바이트가 서버가 보낸 바이트와 같으면 파일이 수신되고 서버가 연결을 종료 할 수 있다고 가정합니다.
  5. 서버에서 다른 파일을 보낼 준비가되었음을 나타내는 표시기로 파일의 바이트 수를받은 다음 다음 바이트를 가정하거나 연결 당 하나의 파일을 받고 싶은 경우 버퍼에서 여분의 바이트를받은 경우 그냥 버립니다. 그것.

파일을받는 다른 방법이있을 수 있으며 다운로드 관리자에서 언젠가는 볼 수 있습니다. 청크로 파일을 깨거나 동일한 연결을 사용하여 여러 파일을받는 것과 같지만 일단 프로토콜을 설정하면 향상된 기능을 쉽게 파악할 수 있습니다.

희망이 있습니다.

의사

은 파일 크기를 초과하는 모든 바이트 (들)을 폐기합니다. fwrite 전에 다음을 시도하십시오.

if(FilzeSize > TotalSize) 
    { 
     fr_block_sz = fr_block_sz - (FilezeSize - TotalSize); 
    } 
    int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr); 

마지막 2 바이트를 제외한 revbuf를 작성해야합니다.

감사 Kajal

+0

응답 Kajal을 보내 주셔서 감사합니다. 나는 성공적으로 1 - 3 단계를 마쳤습니다 (조금 다르긴하지만). 그러나 4 단계에서 종종 반복되지만 파일은 성공적으로 완료되지 않습니다. – 4r4r4r

+0

또한 5 단계에서 여분의 바이트를 무시하는 방법에 대한 의사 코드를 게시 할 수 있습니까? 게시 한 코드에 문제가있는 것이 있습니까? 감사. – 4r4r4r

+0

쿨! 같은 연결에서 여러 파일을 하나씩 차례로 보내보십시오. –

관련 문제