Передача файла в блоках - PullRequest
0 голосов
/ 28 октября 2009

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

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

  • 500 байт,
  • , затем 500 байтов,
  • затем 234 байта

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

Мои процедуры сокетов:

int readn(sd, chunk, bytesToRead);

int writen(sd, chunk, bytesToWrite);

Ответы [ 4 ]

3 голосов
/ 28 октября 2009

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

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

Вопрос по домашнему заданию?

1 голос
/ 28 октября 2009

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

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;
  }

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

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 ().

0 голосов
/ 28 октября 2009

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

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

0 голосов
/ 28 октября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...