저는 C에서 소켓 프로그래밍을 처음 사용하기 때문에 아래의 코드는 초보자 용으로 많은 실수를 범할 수 있습니다. 서버가 UDP 소켓을 사용하여 클라이언트로 파일을 전송할 클라이언트 - 서버 응용 프로그램을 만들려고합니다. 클라이언트와 서버 모두 Linux 호스트에서 실행됩니다. 과제이기 때문에 그렇게해야합니다. 다른 클라이언트 - 서버 통신은 TCP 소켓을 사용할 수 있지만 파일 전송은 UDP를 통해 이루어져야합니다. 이 프로그램은 작은 파일에 대해서는 올바르게 작동하지만, 약간 큰 파일 (예 : 600KB 텍스트 파일)을 보내려고하면 서버가 패킷을 모두 보내더라도 클라이언트는 패킷 수신을 중단합니다. 다음은 서버 코드의 파일 전송 부분입니다.C에서 UDP 소켓을 사용하여 파일 전송하기
FILE* myFile;
long fileSize, readBytes, sentBytes, sizeCheck;
uint32_t encodedFileSize;
myFile = fopen(fileName, "rb");
if(myFile == NULL)
{
perror("Error when opening file.");
exit(1);
}
fseek(myFile, 0, SEEK_END);
fileSize = ftell(myFile);
encodedFileSize = htonl(fileSize);
rewind(myFile);
sizeCheck = 0;
write(myTCPSocket, &encodedFileSize, sizeof(encodedFileSize));
if(fileSize > 255)
{
while(sizeCheck < fileSize)
{
readBytes = fread(bufferRW, 1, 256, myFile);
sentBytes = sendto(sockfdUDP, bufferRW, readBytes, 0, (struct sockaddr*)&cli_addr, udpAddressSize);
sizeCheck += sentBytes;
}
}
else
{
readBytes = fread(bufferRW, 1, 256, myFile);
sentBytes = sendto(sockfdUDP, bufferRW, readBytes, 0, (struct sockaddr*)&cli_addr, udpAddressSize);
}
if(fileSize == sizeCheck)
{
printf("Success.\n");
}
else
{
printf("Fail.\n");
}
fclose(myFile);
fflush(stdout);
close(sockfdUDP);
위에서 알 수 있듯이 TCP 소켓을 사용하여 클라이언트에게 파일 크기를 보냅니다. 여기서 클라이언트 코드는 :
FILE *myFile;
long receivedBytes, writtenBytes, sizeCheck;
long fileSize, realFileSize;
char ack2[5] = "Ok";
sockfdUDP = socket(AF_INET, SOCK_DGRAM, 0);
read(socketTCP, &fileSize, sizeof(long));
realFileSize = ntohl(fileSize);
myFile = fopen(fileName, "wb");
if(myFile == NULL)
{
perror("Error when creating file.");
exit(1);
}
sizeCheck = 0;
if((realFileSize) > 255)
{
while(sizeCheck < (realFileSize))
{
receivedBytes = recvfrom(sockfdUDP, bufferRW, 256, 0, (struct sockaddr*)&serv_addr, &serv_addr_size);
writtenBytes = fwrite(bufferRW, 1, receivedBytes, myFile);
fflush(myFile);
sizeCheck += writtenBytes;
}
}
else
{
receivedBytes = recvfrom(sockfdUDP, bufferRW, 256, 0, (struct sockaddr*)&serv_addr, &serv_addr_size);
fwrite(bufferRW, 1, receivedBytes, myFile);
fflush(myFile);
}
if(realFileSize == sizeCheck)
{
printf("Success.");
}
else
{
printf("Fail.");
}
fclose(myFile);
close(sockfdUDP);
은 "bufferRW"버퍼
원래 선언 CHAR bufferRW [256], 인수로서 함수에 전달있다. 선언되지 않은 다른 변수에 대해서도 마찬가지입니다. 전에 말했듯이, 서버는 아무런 문제없이 (분명히) 전체 파일을 보낼 것입니다. 그러나 클라이언트는 약 423936 바이트 (실행마다 달라질 수 있음)를 작성한 후에 패킷 수신을 중지합니다. 그냥 아무것도 읽지 않고 recvfrom 줄에 머무를거야.이제 동일한 호스트에서 두 프로세스를 테스트 중이므로 잘못된 연결로 인해 문제가 발생하지 않았 음을 확신합니다. 그리고 "256 바이트 패킷 크기는 무엇입니까?"라는 질문을하기 전에 1500이라는 버퍼 크기를 사용하면 realFileSize = ntohl(fileSize);
클라이언트 라인에 세그멘테이션 오류가 발생합니다.
너 내가 뭘 놓치고 있는지 말해 줄래?
편집 : 이제 다른 파일 크기로 시도하고 있습니다. 문제없이 256 바이트보다 큰 파일을 처리하는 것 같습니다 (클라이언트와 서버 모두에서 while 루프가 올바르게 시작되고 종료됩니다). 그러나 클라이언트는 파일이 300kb보다 클 때 문제가 발생하기 시작합니다.
편집 2 : 방금 프로그램을 디버깅했습니다. 분명히, 서버는 클라이언트가 while 루프를 입력하기 전에 전체 파일을 보냅니다.
편집 3 : 문제의 원인을 알고 있다고 생각합니다. 클라이언트가 읽기를 시작하기 전에 서버가 많은 패킷을 보내는 것처럼 클라이언트는 크기에 관계없이 최대 278 개의 패킷을 읽습니다. 클라이언트가 읽기를 시작하기 전에 279를 전송하려고하면 279 번째 패킷을 읽지 않습니다. 따라서 서버가 패킷을 충분히 빨리 보내면 클라이언트가 아직 읽지 않은 패킷 수가 278을 초과하고 클라이언트가 모든 패킷을 읽지 못하게됩니다. 이 문제를 해결하는 방법에 대한 아이디어가 있습니까?
당신이 UDP를 사용한다면, 당신은 현재하지 않고있는 패킷 방울과 재정렬을 처리해야한다는 것을 알기를 바랍니다. – icktoofay