Сообщения, использующие gen_tcp:send, не отправляются до тех пор, пока сокет не будет закрыт
Я хочу написать простой клиент, который отправляет сообщение на сервер и получает ответ. У меня есть сервер, который передает одно и то же сообщение всем подключенным клиентам, и он работает, когда я тестирую его с помощью 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 ответа
Основная проблема в том, что универсального формата сообщений не существует. Итак, ваш первый шаг - выяснить, какой формат сообщения использует сервер. Вы не можете говорить с сервером на другом языке.
Некоторые форматы сообщений могут быть:
- Весь поток - это сообщение.
- Сообщения фиксированного размера.
- Сообщения, разделенные маркером. Например, SMTP, POP, HTTP и многие другие протоколы используют этот тип сообщений.
- Сообщения с размером поля. Например, формат сообщения TLV (Type-Length-Value). 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").
При отправке небольших порций данных сокет буферизует их, чтобы попытаться заполнить максимальную полезную нагрузку для пакета TCP.
Вполне возможно, что это именно то, что происходит, потому что когда вы закрываете сокет, он очищается до того, как он освобождается.
Попробуйте установить
{nodelay, true}
вариант на вашем сокете.
Более подробная информация здесь: http://www.erlang.org/doc/man/inet.html
Вы можете попробовать это на сервере Erlang, чтобы увидеть, есть ли проблемы на стороне сервера или клиента.
В оболочке А:
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.