Я довольно новичок в программировании сокетов на C, поэтому в приведенном ниже коде может быть много ошибок новичка. Я пытаюсь создать клиент-серверное приложение, в котором сервер будет передавать файл клиенту с использованием сокета UDP. И клиент, и сервер будут работать на хостах Linux. Это задание, так что это должно быть сделано именно так. Другие коммуникации клиент-сервер могут использовать сокет TCP, но передача файлов ДОЛЖНА быть через UDP. Программа работает корректно для небольших файлов, но если я попытаюсь отправить немного больший файл (скажем, текстовый файл размером 600 килобайт), клиент перестанет получать пакеты, даже если сервер отправит их все. Вот передача файла часть кода сервера:Перенос файлов с использованием сокетов UDP в C
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» буфер был первоначально объявлен как полукокс bufferRW [256] и передаются функции в качестве аргумента. То же самое касается других необъявленных переменных. Как я уже говорил, сервер (по-видимому) отправит весь файл без каких-либо проблем. Тем не менее, клиент перестанет получать пакеты после того, как будет написано около 423936 байт (это может варьироваться в зависимости от исполнения). Он просто останется на линии recvfrom, не прочитав ничего.
Теперь я уверен, что проблема не вызвана неправильным подключением, так как я тестирую оба процесса на одном хосте. И прежде чем вы спросите: «Что это такое с размером пакета в 256 байтов?», Есть такая странная ошибка, которая вызовет у меня ошибку сегментации на клиентской линии realFileSize = ntohl(fileSize);
, если я использую размер буфера, например, 1500.
Не удалось скажите, пожалуйста, что мне здесь не хватает?
EDIT: Я пытаюсь с разными размерами файлов сейчас. Кажется, что он обрабатывает файлы размером более 256 байт без проблем (он входит и выходит из цикла while правильно и на клиенте, и на сервере), но у клиента появятся проблемы, когда файл больше, чем, скажем, 300 кб.
EDIT 2: Я только что отладил программу. По-видимому, сервер отправляет весь файл до того, как клиент может даже ввести свой цикл while.
EDIT 3: Я думаю, что знаю, что вызывает проблему. Похоже, если сервер отправляет кучу пакетов до того, как клиент начнет чтение, клиент будет считывать до 278 пакетов независимо от их размера. Если я попробую отправить, скажем, 279, прежде чем клиент начнет читать, он не прочитает 279-й пакет. Поэтому, если сервер достаточно быстро отправляет свои пакеты, количество пакетов, которые клиент еще не прочитал, превысит 278, и клиент не завершит чтение всех пакетов. Есть какие нибудь идеи как это починить?
Надеюсь, вы поймете, что если вы используете UDP, вам придется иметь дело с падением пакетов и переупорядочением самостоятельно, чего вы сейчас не делаете. – icktoofay