Остановить и дождаться протокола передачи файлов, когда прекратить прослушивание? - PullRequest
3 голосов
/ 06 марта 2012

Я разрабатываю клиентское и серверное приложение для передачи файлов с сокетами C ++ по UDP (SOCK_DGRAM).Для метода PUT у меня есть следующее выполнение (после рукопожатия):

client

Send a packet;
if time_out
    send the packet again;
else  //ack received
    send a new packet;

server

wait for the first packet;
send acknowledge;
while(!EOF)
    Get a packet;
    Send an ack;

Где EOF в основном проверяетесли я получил весь файл по сравнению с размером файла, который я посылаю во время рукопожатия.

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

Моя путаница возникает в конце передачи файла.Клиент только что отправил пакет, содержащий последние биты файла.Сервер успешно получает его и отправляет свой ACK.Этот пакет теряется.Серверное приложение теперь находится вне цикла while, потому что он записал последние биты в файл и, с его точки зрения, передача файла прошла успешно.Однако клиент так и не получил ACK, поэтому время ожидания истекло и он повторно отправляет пакет данных.Что здесь должно произойти?Сервер не прослушивает или ожидает новый запрос, а не данные.В какой момент клиент или сервер должны считать передачу завершенной и перестать пытаться связаться?

Ответы [ 2 ]

2 голосов
/ 06 марта 2012

Похоже, вы заново изобретаете TFTP , но с ролями клиента и сервера в обратном направлении. Вы уверены, что вам нужно это сделать? Это очень неэффективный протокол из-за отсутствия скользящего окна или конвейера данных.

Я вижу 3 решения вашей головоломки:

  • Трехстороннее рукопожатие в конце передачи файла. После получения последнего блока данных сервер не только отправляет ACK, но и ждет, пока клиент подтвердит ACK. Когда это происходит, сервер знает, что клиент знает, что передача файла завершена. Если сервер никогда не получает ACK ACK, он периодически повторно отправляет ACK последнего блока данных.
  • Сервер запоминает завершенные передачи файлов в течение нескольких минут после их завершения (или нескольких RTT, в зависимости от того, что больше). Если в течение этого времени он получает какой-либо блок данных от клиента для передачи файла, которая, как предполагалось, уже завершена, сервер просто подтверждает это, не предпринимая никаких действий, и сбрасывает таймер окончания передачи для этой передачи файла. Это более сложная задача, но она имеет преимущество перед предыдущим решением, заключающееся в том, что сервер мог двигаться дальше и выполнять другую работу после завершения передачи файла.
  • Сервер отвечает с ошибкой (NAK), если он когда-либо получает какой-либо блок данных, который не является частью активной передачи файла. Это относится к тому, является ли это частью несуществующей, недействительной или уже завершенной передачи. Это самый простой для реализации, но также и самый уродливый, потому что клиент должен завершиться с ошибкой, когда он получает этот NAK. Но, возможно, все в порядке, потому что передача файла все еще была успешной с точки зрения сервера.
1 голос
/ 06 марта 2012

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

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

...