Обработка пакетов разных размеров с использованием сокетов в C - PullRequest
1 голос
/ 06 августа 2010

, который является чудовищным подходом к отправке пакетов, которые могут быть разного размера, используя TCP-сокеты в C?

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

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

Ответы [ 3 ]

1 голос
/ 06 августа 2010

Создайте статическую переменную, которая представляет заголовок пакета, эта переменная будет иметь длину пять байтов.Создайте связанное целое число, которое подсчитывает, сколько из этих пяти байтов еще было прочитано.Создайте второе целое число, которое подсчитывает, сколько байтов «содержимого» было прочитано.Обнулите оба целых числа.Создайте связанный указатель char *, который в конечном итоге будет указывать на содержимое принятого пакета.

По мере поступления данных (например, select указывает на это), прочитайте пять байтов заголовка.Вы можете получать эти байты постепенно, поэтому вам нужна первая переменная целочисленного числа.Учет байтов заголовков, которые вы получили здесь.

Когда вы закончите получать заголовок, рассмотрите его.Можно ли удовлетворить значения размера (например, не более 2 ^ 30)?Если это так, malloc буфер этого размера или этого размера плюс заголовок.(Если вы хотите, чтобы заголовок был непрерывным, выделите достаточно места, затем memcpy поместите его в новый буфер.)

Теперь, когда данные поступают, поместите их в выделенный буфер.Учет полученных байтов во втором целом числе, которое вы создали.Когда вы получите все байты, которые требует заголовок, повторите все вышеперечисленное.

1 голос
/ 06 августа 2010

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

некоторый примерный псевдокод, следующий:

recv(socket, headerBuf, headerSize, MSG_WAITALL);
nPacketSize = headerBuf[16];    //sample
nByteRead = 0;

while (nByteRead != nPacketSize)
{
    nByteToRead = nPacketSize - nByteRead;
    nCurRead = recv(socket, someBuf, nByteToRead, MSG_PARTIAL);

    nByteRead += nCurRead;
    Sleep(0);   // Yield processor
}
0 голосов
/ 06 августа 2010

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

Примеры таких протоколов включают HTTP, где HTTP-сообщения очерчены двумя последовательными возвратами каретки, парами перевода строки. \r\n\r\n. Единственная проблема, связанная с таким разграничением, состоит в том, чтобы убедиться, что шаблон не может присутствовать в теле сообщения, либо в этом, либо чтобы убедиться, что оно экранировано. Другие протоколы создают заголовок, который содержит информацию, необходимую для правильной идентификации и чтения следующего фрагмента информации. Я не могу думать о приложении, которое делает это из головы. Вы могли бы даже пойти на гибридный подход, который сочетает в себе два.

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