Сообщения, использующие gen_tcp: send, не отправляются до тех пор, пока сокет не будет закрыт - PullRequest
0 голосов
/ 08 сентября 2011

Я хочу написать простой клиент, который отправляет сообщение на сервер и получает ответ. У меня есть сервер, который передает одно и то же сообщение всем подключенным клиентам, и он работает, когда я тестирую его с помощью telnet. Когда я пытаюсь сделать это с помощью оболочки Erlang, gen_tcp: send не будет отправлять сообщения, пока я не закрою сокет.

Вот что я пытаюсь сделать:

{ok, S} = gen_tcp:connect(IP, Port, []).
gen_tcp:send(S, "Test").
flush().

Я вижу, что сообщение отправляется, когда я закрываю сокет, глядя на моего клиента telnet.

Версия Erlang: R14B01 (erts-5.8.2)

Обновление

hdima прокомментировал и сказал, что это может быть неправильно с тем, как сервер извлекает сообщения из потока. Кажется, это одна из причин, по которой я пытался написать свой собственный сервер, а клиент работает так, как ожидалось. Я постараюсь получить исходный код сервера. Сервер написан на Java, кстати.

Ответы [ 3 ]

3 голосов
/ 12 сентября 2011

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

Возможно, это то, что происходит, потому что когда вы закрываете сокет, он очищается до того, как он будет освобожден.

Попробуйте установить параметр

{nodelay, true}

наВаш сокет.

Больше информации здесь: http://www.erlang.org/doc/man/inet.html#setopts-2

1 голос
/ 10 сентября 2011

Основная проблема в том, что существует нет Универсальный формат сообщения. Итак, ваш первый шаг - выяснить, какой формат сообщения использует сервер. Вы не можете говорить с сервером на другом языке.

Некоторые форматы сообщений могут быть:

  • Весь поток - это сообщение.
  • Сообщения фиксированного размера.
  • Сообщения, разделенные маркером. Например, SMTP , POP , HTTP и многие другие протоколы используют этот тип сообщений.
  • Сообщения с полем размера. Например, TLV (тип-длина-значение) формат сообщения. IP , UDP , Erlang и многие другие протоколы используют этот тип сообщений.

Например, если сервер понимает сообщения, разделенные символом перевода строки, вы можете отправить два отдельных сообщения со следующим кодом:

1> {ok, S} = gen_tcp:connect(IP, Port, []).
2> gen_tcp:send(S, "Test\n").
3> gen_tcp:send(S, "Test2\n").
0 голосов
/ 09 сентября 2011

Вы можете попробовать это на сервере Erlang, чтобы увидеть, есть ли проблемы на стороне сервера или клиента.

В оболочке A:

1> {ok, L} = gen_tcp:listen(12345, [{active, false}]).
{ok,#Port<0.601>}
2> {ok, S} = gen_tcp:accept(L), {ok, P} = gen_tcp:recv(S, 0), gen_tcp:send(S, P).
... % Server will block here until a message comes
ok

В оболочке B:

1> {ok, S} = gen_tcp:connect(localhost, 12345, []), gen_tcp:send(S, "hello").
ok
2> flush().
Shell got {tcp,#Port<0.607>,"hello"}

Если это работает, это, скорее всего, проблема на стороне Java.

...