2009-10-28 3 views
0

В C (UNIX), как я могу передать и получить файл в нескольких блоках с помощью сокета?Перенос файла в блоки

Например, если у меня был файл байт, а размер блока 500, я бы передать:

  • 500 байт,
  • затем 500 байт,
  • затем 234 bytes

Я попытался использовать fseek, читать, писать, но я просто не могу получить логику. Даже хорошая рекомендация будет высоко оценена.

Мои сокетов подпрограммы:

int readn(sd, chunk, bytesToRead); 

int writen(sd, chunk, bytesToWrite); 
+0

Что не работает правильно? Проверяйте эти функции отдельно, комментируя всю дальнейшую часть ..... просто проверяйте ее эхо (cout) файл чтения на консоль – Xinus

+1

Возможно, вы неправильно поняли, как работают сокеты. Если вы используете подключенный (TCP) сокет, тогда данные концептуально являются потоком.Фактические вызовы для чтения и записи делают кусок данных за раз, но им не обязательно соответствовать. Читатель и писатель могут использовать любые размеры, которые им нравятся, просто обязательно проверьте возвращаемые значения. Только с сокетами UDP (без установления соединения), которые читатель и писатель должен манипулировать одними и теми же фрагментами, и вам редко нужен UDP, за исключением некоторых высокопроизводительных ситуаций. –

+0

Итак, предположим, что писатель пишет 500 байтов, затем 500, затем 234, успешно. Затем читатель может читать до 1234 байта в одном запросе на чтение, если он снабжает достаточно большой буфер. Точно так же, если писатель записывает 1234 байта за один раз, тогда нет ничего плохого в чтении считывателя в блоках 500 или 128 или любом другом размере. Сеть прерывает поток в пакеты под обложками, но вы можете игнорировать это, если вы не используете UDP. И когда вы пишете или читаете сокет, вы почти наверняка никогда не должны использовать поиск. –

ответ

3

Если вы используете TCP, то все, что вам нужно сделать, это отправить блок данных (я предполагаю, что у вас есть какой-то протокол, который говорит вам, сколько байтов в блок, такой как заголовок?), и когда вы получите свой блок на другом конце, просто напишите его в файл, который вы пишете. TCP будет иметь дело с тем, чтобы все прибывало в ожидаемом порядке, чтобы вы могли просто пробираться через чтение файла в X байтах за раз и отправлять их, а затем на стороне recv вы просто возвращаете свои данные и записываете их к файлу ... Просто помните, что каждый прочитанный вами выпуск на вашем сокете может возвращаться где угодно между 1 и байтами размера блока и что ваш протокол должен быть в состоянии рассказать вам, сколько ожидать, и что вы должны зацикливаться до тех пор, пока вы не фактически получил столько байт, как и следовало ожидать ...

Если вы используете UDP, то все становится немного больше удовольствия, как вам нужно, чтобы отслеживать, какие блокировать конкретный дейтаграмма представляет ...

Homework вопрос ?

+1

+1 для указания, что запись N байтов не обязательно вызывает чтение N байтов на принимающей стороне. И, может быть, стоит отметить, что при использовании TCP две записи по N байтам не обязательно вызывают два чтения из N байтов, если максимальный размер для буфера приема больше N. –

+0

Andrew, Действительно, но я ожидал, что протокол вокруг блоков (просто заголовок, который сообщает нам размер?), будет означать, что чтение, вероятно, будет иметь «ожидаемыйBlockSize - bytesWeAlreadyHaveForThisBlock» ... Но стоит упомянуть явно свойство writeSize! = readSize. –

0

У вас есть правильная идея. Главное, чтобы убедиться в том, что вы IO-вызовы действительно делают то, что вы им говорите ... Это означает проверку их кодов возврата, чтобы убедиться, что они написали или прочитали сумму, которую вы ожидали ... Кроме того, она выглядит например, вы завернули чтение и запись ... Возможно, вам следует начать с того, чтобы убедиться, что они полностью правильны ...

0

Чтение будет содержать только столько байтов, сколько на самом деле буферизовано в это время, или указана максимальная игрушка. Поэтому, если вы часто читаете, вы получите гораздо меньшие куски. Если это имеет значение (и я не могу понять, почему это должно), вам нужно сопоставить данные во вторичном буфере, пока не получите ожидаемое число.

Конечно, есть прекрасные протоколы передачи файлов, такие как FTP, которые вы могли бы использовать вместо этого.

1

Из верхней части головы (не скомпилированный, поэтому увидеть его как псевдокод):

bytesRemaining = 1234; 
chunkSize = 500; 
offset = 0; 
bytesWritten = 0; 

while(bytesRemaining > 0) 
    { 
    if(bytesRemaining < chunkSize) 
     bytesToWrite = bytesRemaining; 
    else 
     bytesToWrite = chunkSize; 

    writen(sd, chunk+offset, bytesToWrite); 
    offset += bytesToWrite; 
    bytesRemaining -= bytesToWrite; 
    } 

или если прописан() возвращает количество байт написано:

bytesRemaining = 1234; 
chunkSize = 500; 
offset = 0; 
bytesWritten = 0; 

while(bytesRemaining > 0) 
    { 
    if(bytesRemaining < chunkSize) 
     bytesToWrite = bytesRemaining; 
    else 
     bytesToWrite = chunkSize; 

    bytesWritten = writen(sd, chunk+offset, bytesToWrite); 
    offset += bytesWritten; 
    bytesRemaining -= bytesWritten; 
    } 

Та же логика может применяться к случаю readn().

Смежные вопросы