2009-03-26 1 views
6

Я пытаюсь получить некоторый файл через сокеты в C. Но сервер отправляет мне 64-байтные пакеты для 1000000 байтового файла, например, и я получаю приблизительно 999902 байта на файл назначения.Передача файла через сокеты, конечный размер с меньшим количеством байтов

while ((n = read(sd, buffer_in, BUFSIZE))) // BUFSIZE = 64 
{ 
    if(n<0) 
    { 
     printf("Fail.\n"); 
     fclose(archivo); 
     return -1; 
    } 

    if(fwrite(buffer_in, n, 1, f) !=1) 
    { 
     printf("fwrite error.\n"); 
     fclose(archivo); 
     return -1; 
    } 

    bytes+=n; 
} 

printf("We received %d bytes", bytes); 

При использовании через локальный сокет TCP/IP он работает, но не в медленном соединении. Я вижу через отладку, что я получаю много 64 байтовых кусков и 30-байтовый кусок возле EOF. Я знаю, что вы можете получить меньше байтов на read(), поскольку вызов возвращается, когда доступны любые данные (> 1 байт). Но это условие не должно быть улавливано временем? Должен возвращаться, когда n == 0, это больше не данные (EOF).

Thx для вашей помощи.

(EDIT)

Отправка кода следующим образом:

while (n=read(file_fd, buffer, BUFSIZE)) 
{ 
    write (sdaccept, buffer, n) 
} 

Я знаю, что и для чтения() и записи() может возвращать N < BUFSIZE, но не следует этого цикла работы, что соответственно ? Я добавил n и возвращает 1000000, точный размер.

(EDIT II)

Испытано с источником C с 10673 байт, получает 10575 без коррупции, за исключением того, что файл назначения НЕДОСТАТКИ первые 98 байт !!!

+0

Приблизительно 999902? Или точно? – paxdiablo

+0

Я не вижу явных недостатков в этом коде - пожалуйста, покажите код отправки. – Alnitak

+0

особенно странно, так как 64 делит на 1000000 точно –

ответ

11

Предоставленный код отправки игнорирует тот факт, что write() (или send()) в сокете не обязан записывать весь буфер.

write()/send() может решить записать его частично или вообще не писать, если базовая подсистема отказывается получать больше данных (например, сетевая подсистема может иметь очередь для отправки данных, и эта очередь уже полный). Это очень вероятно при медленном соединении.

Отправляющая сторона должна проверить возвращаемое значение write(), чтобы определить, сколько данных было фактически записано и соответствующим образом отрегулировано.

Запись должна быть сделана как-то так:

int readAmount; 
while(readAmount = read(file_fd, buffer, BUFSIZE) > 0) 
{ 
    int totalWritten = 0; 
    do { 
     int actualWritten; 
     actualWritten = write (sdaccept, buffer + totalWritten, readAmount - totalWritten); 
     if(actualWritten == - 1) { 
      //some error occured - quit; 
     } 
     totalWritten += actualWritten; 
    } while(totalWritten < readAmount); 
} 
+0

Добавлен дополнительный код отправки. –

+0

Отправляющий код подвержен именно той проблеме, которую я описал. Добавлено исправление. – sharptooth

+0

Все еще передает 999902 байт !!!! :(:( –