Сокеты - разница между отправкой C и Java - PullRequest
1 голос
/ 10 декабря 2010

Я конвертирую приложение Java (используя NIO) в сокеты C и столкнулся с проблемой.В то же время я использую grinder в качестве TCPProxy, чтобы увидеть, что было передано.

У меня есть 4 строки, для которых мне нужно отправить клиенту как часть рукопожатия.

Hello~Server\r\n
Hello1~Server1\r\n
Hello2~Server2\r\n
Hello3~Server3\r\n

Для приложения Java (с использованием NIO) каждая строка отправлялась после каждого броска Java NIO ().То есть вышеперечисленные 4 строки рассылаются по одной за раз.

У меня есть следующий псевдокод для Java.

  1. Очистить буфер,
  2. Поместить строку в буфер,
  3. Поместить размер строки,
  4. Flip.

Для сокетов C все 4 массива символов были отправлены вместе, хотя у меня есть 4 отдельных функции send ().

Stumped.Есть идеи?

Ответы [ 3 ]

3 голосов
/ 10 декабря 2010

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

Сказав это, вы можете попытаться включить "сосредоточение" через setsockopt с опцией TCP_NODELAY.

1 голос
/ 10 декабря 2010

Сообщения, отправленные вашим C-кодом, вероятно, объединяются в один пакет по алгоритму Нейгла . Вы можете отключить это, установив параметр TCP_NODELAY на сокете отключить алгоритм Nagle. Однако вы должны иметь в виду, что TCP не обязан соблюдать границы ваших сообщений, поэтому ваш протокол должен иметь свой собственный способ определения, когда было получено полное сообщение, а не в зависимости от соответствия 1-1 между send () и recv () вызывает в конечных точках.

0 голосов
/ 10 декабря 2010

Спасибо, что нашли время, чтобы дать мне предложения (медленный). Я попытался включить TCP_NODELAY, но это не решило проблему. Почему я сказал «проблема» - ответьте ниже.

Я посмотрел в свой send () и заметил, что я использовал sizeof (сообщение) вместо strlen (сообщение). sizeof () - получает размер байтов для отправки. strlen () - получает количество отправляемых символов, исключая \ 0.

Я был довольно наивен, чтобы следовать тому, что говорилось в справочной странице по Ubuntu.

yakult121 $ man send

ssize_t send (int sockfd, const void * buffer, size_t len, int flags);

Я думал, что аргумент size_t len ​​должен был использовать sizeof (), как я использовал его для memset ().

yakult121 $ man memset

void * memset (void * s, int c, size_t n);

Я также наконец понял, что socklen_t и size_t - это разные типы данных.

Еще раз спасибо всем. Я не смог бы найти проблему и продолжал указывать пальцем на алгоритм Нейгла.

...