【问题标题】:Messages using gen_tcp:send doesn't get sent until the socket is closed使用 gen_tcp:send 的消息在套接字关闭之前不会被发送
【发布时间】:2011-11-13 06:17:24
【问题描述】:

我想编写一个简单的客户端,向服务器发送消息并接收响应。我有一个服务器,它向所有连接的客户端广播相同的消息,并且在我使用 telnet 测试它时它正在工作。当我尝试使用 Erlang shell 执行此操作时, 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 编写的。

【问题讨论】:

  • 看起来服务器不知道如何从流中提取消息。能发下服务器源代码吗?
  • @hdima:不抱歉,我没有服务器代码。

标签: java sockets erlang gen-tcp


【解决方案1】:

你可以用 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 方面的问题。

【讨论】:

  • 如果您阅读更新部分,我已经说过它似乎是服务器。但是感谢您抽出时间并回答!
  • 啊,没发现。 :-) 您也可以回答自己的问题,并将该答案标记为已接受。
  • 我的问题几乎得到了解答,但我想在将任何内容标记为正确之前找出 java 代码有什么问题。
【解决方案2】:

主要问题是没有通用消息格式。因此,您的第一步是找到服务器使用的消息格式。您无法使用其他语言与服务器交谈。

一些消息格式可以是:

  • 整个流就是一条消息。
  • 固定大小的消息。
  • 由标记分隔的消息。例如SMTPPOPHTTP 和许多其他协议都使用这种类型的消息。
  • 带有大小字段的消息。例如TLV (Type-Length-Value) 消息格式。 IPUDPErlang 和许多其他协议都使用这种类型的消息。

例如,如果服务器理解由换行符分隔的消息,您可以使用以下代码发送两条不同的消息:

1> {ok, S} = gen_tcp:connect(IP, Port, []).
2> gen_tcp:send(S, "Test\n").
3> gen_tcp:send(S, "Test2\n").

【讨论】:

  • 发送带有行尾的消息有效。 java 服务器可能正在使用 readLine() 或类似的。谢谢!
  • 我不认为这是正确的。这与服务器期望的消息类型无关。这是由于 Erlang 端的套接字设置。使用 {packet, PacketType} 设置来配置它。
  • @NateC-K 使用 {packet, PacketType} 选项 Erlang 只需为您透明地发送/接收每条消息作为长度值。如果您打算连接用其他语言(如问题中的 Java)编写的服务器/客户端,则必须了解消息格式。
【解决方案3】:

当发送小块数据时,套接字会缓冲它们以尝试填充 TCP 数据包的最大负载。

这可能是正在发生的事情,因为当您关闭套接字时,它会在释放之前被刷新。

尝试设置

{nodelay, true}

您的套接字上的选项。

更多信息在这里: http://www.erlang.org/doc/man/inet.html#setopts-2

【讨论】:

  • 这是最好的答案。客户端正在缓冲数据。它与服务器无关。关键设置是 {packet, PacketType},您链接到的部分对此进行了说明。
猜你喜欢
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-07
  • 1970-01-01
  • 2012-12-13
  • 2017-06-13
相关资源
最近更新 更多