Сокеты: отправьте 2Mb без потери данных - PullRequest
0 голосов
/ 01 июня 2011

Я использую сокеты в Linux, и я хотел бы отправить большую таблицу (более 2 Мб) без потери данных и достаточно быстро, чтобы иметь плавное видео на клиенте. (то, что я посылаю, это видео поток).

Я пробовал две вещи:

1 °) отправить всю таблицу за один раз

socketError = send(newsockfd,(char*) DataTab,sizeof(DataTab),0);
if (socketError < 0)
    error("ERROR server writing to socket");

2 °) отправьте элементы по одному

for (int i=0; i<nbelem; i++) // nbelem is greater than 600'000
{
    socketError = send(newsockfd,(char*) &DataTab[i],sizeof(&DataTab[i]),0);
    if (socketError < 0)
    error("ERROR server writing to socket");
}

Очень быстрая отправка таблицы, но я теряю некоторые данные.

Отправка элементов по одному работает нормально, без потери данных, но это слишком медленно.

Итак, у меня есть 2 вопроса: Каково ограничение данных, которые могут быть отправлены в одном сокете (в байтах)? и Как я могу отправить свою таблицу быстро и без потери данных?

PS: Мои программы должны общаться в локальной сети или в сети Ethernet. Интернет-общение не предусмотрено.

Ответы [ 4 ]

2 голосов
/ 01 июня 2011

Самый простой ответ: используйте сокет tcp: socket(AF_INET, SOCK_STREAM, 0).

Более сложный ответ: если вы хотите использовать udp, используйте (или придумайте) какой-нибудь протокол с проверкой доставки, повторной передачей и, возможно, с контролем перегрузки.

1 голос
/ 01 июня 2011

Как правило, UDP является хорошей идеей для отправки данных видеопотока, поскольку потеря видеоданных обычно допускается !

Если вы не должны терять данные, рассмотрите возможность использования TCP в соответствии с предложением!

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

Если вы можете позволить себе хорошее предположение, сделайте размер пакета 1492.

РЕДАКТИРОВАТЬ:

Если вы используете Windows, рассмотрите возможность увеличения размера буфера приемника:

int bufferSize = 64 * 1024;  // 64k
setsockopt( socket, SOL_SOCKET, SO_RCVBUF, (char *) & bufferSize );
0 голосов
/ 03 июня 2011

Ну, вы не ответили, используете ли вы UDP или нет.Если вы , то это ваш ответ.Максимальный размер датаграммы для UDP составляет 64 КБ.Так что он не поддерживает send() из 2 МБ.Поэтому первое, что вам нужно сделать (чтобы продолжить использовать UDP), - это разбить его на куски размером не более 64 КБ.

Однако даже это неоптимально.Это связано с тем, что ваш базовый канальный уровень, скорее всего, не поддерживает пакеты где-то рядом.UDP автоматически обрабатывает это, разбивая дейтаграмму на передачи размером с пакет.Однако UDP очень упрощен.Если какой-либо из этих пакетов будет потерян или каким-либо образом потерян, вся дейтаграмма должна быть выброшена.TCP, с другой стороны, просто повторно отправит отсутствующий пакет.Если ваша дейтаграмма UDP состоит только из пары или трех пакетов, это может быть не очень большим.Но (при условии стандартного размера данных 1420 или около того) для всех ваших передач потребуется отсутствие сбоя в 33 отдельных дейтаграммах по 47 IP-пакетов в каждой.

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

Именно поэтому многие считают, что переключение на TCP может быть проще для вас.Он обрабатывает все это в своем протоколе.

0 голосов
/ 02 июня 2011

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

Если видео отправляется через Интернет и вам нужна надежность, вы должны использовать TCP. Если вы используете TCP, то просто send() все данные за один раз. TCP имеет встроенную надежность и механизм управления потоком. В этом случае мало что можно сделать, чтобы ускорить передачу данных.

Вы также можете рассмотреть возможность использования Raw-сокетов и реализовать собственную надежность и управление потоком. Иначе, работайте над своим приложением, чтобы оно работало нормально, даже если есть пара потерянных видеокадров.

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