Как я могу отправлять файлы асинхронно в клиент-серверном приложении? (Используя winsock2.h, в C) - PullRequest
1 голос
/ 22 марта 2019

Я хочу отправлять файлы асинхронно.Я отправил файл клиент-> сервер-> другой клиент, но если я хочу отправить очень большой файл, клиент не может отправлять какие-либо другие команды на сервер, пока файл не будет полностью отправлен.Для каждого файлового клиента, который хочет отправить, я создаю новый поток, в котором я буду читать 1 КБ файла за раз и отправлять на сервер, затем сервер получит 1 КБ и отправит дальше желаемому клиенту.Проблема в том, что когда клиент отправляет файл, сокет заполнен байтами с сервера.Я должен сделать один сокет клиент-сервер для каждого файла, который я хочу отправить?Я перепробовал все, но ничего не получилось.

Ответы [ 2 ]

2 голосов
/ 22 марта 2019

Создание выделенных сокетов для каждой передачи - это одно решение, и оно неплохое, если только количество одновременных подключений не велико (в системе доступно только столько IP-портов, а серверу потребуется вдвое больше). Потоки не настолько упрощают это, как вы думаете, и создают свои собственные проблемы; select - это более простой способ эффективной передачи данных по нескольким сокетам из одного потока / процесса. Он работает, раскрывая знания базовой операционной системы о том, какие сокеты готовы для чтения и записи в программу.

Сложность для вас с подходом с несколькими сокетами, независимо от выбора потоков, заключается в том, что сервер должен будет сказать получателю об открытии нового соединения с сервером для каждой новой передачи. Теперь вам нужна команда mechansim, чтобы сообщить получателю, что нужно открыть новое соединение для следующего файла.

Другой вариант - открыть только один сокет, но одновременно отправить несколько файлов через сокет. Вы можете сделать это, отправив структуру данных, содержащую следующие части каждого файла, вместо того, чтобы просто передавать файл напрямую. Например, вы можете отправить сообщение, которое выглядит примерно так (для ясности представлено в JSON, но это будет допустимый транспортный формат):

[ 
  { 
    "name": "file.txt", 
    "bytes": "some smallish chunk of content", 
    "eof": false
  },
  { 
    "name": "another.txt", 
    "bytes": "chunk of another.txt content", 
    "eof": true
  }
]

Этот пример, конечно, наивно упрощен, но, надеюсь, этого достаточно, чтобы донести идею: структурируя отправляемые сообщения, вы можете описать, к каким файлам принадлежат отдельные куски байтов, а затем отправить несколько кусков нескольких файлы сразу. Из-за вашего подхода «клиент-> сервер-> клиент» мне кажется, что это лучший путь вперед.

0 голосов
/ 23 марта 2019

используя структуру, аналогичную:

struct transferPacket
{
    unsigned packetOfFile;  // = 0 when starting a new file
    unsigned fileNumber;    // incremented with each new file
    unsigned byteCount; 
    char     payload[ MAX_PAYLOAD_LEN ];
};

Когда packetOfFile == 0, тогда запуск нового файла и полезной нагрузки содержит имя файла. В противном случае указывает, какая часть файла передается.

Когда byteCount= 0, тогда EOF для этого fileNumber

Выше указано только, что для одного сокета TCP

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

Отправитель каждый раз отправляет одно и то же количество байтов, за исключением первого пакета файла и пакета EOF илипоследний пакет данных файла

...