【发布时间】:2014-07-06 14:36:19
【问题描述】:
正如标题所说,我有一个用 Erlang 编写的服务器,一个用 Java 编写的客户端,它们通过 TCP 进行通信。我面临的问题是 gen_tcp:recv 显然不知道何时收到来自客户端的“完整”消息,因此将其“拆分”为多条消息。
这是我正在做的一个例子(不完整的代码,试图只保留相关部分):
代码
Erlang 服务器
-module(server).
-export([start/1]).
-define(TCP_OPTIONS, [list, {packet, 0}, {active, false}, {reuseaddr, true}].
start(Port) ->
{ok, ListenSocket} = gen_tcp:listen(Port, ?TCP_OPTIONS),
accept(ListenSocket).
accept(ListenSocket) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
spawn(fun() -> loop(Socket) end),
accept(ListenSocket).
loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
io:format("Recieved: ~s~n", [Data]),
loop(Socket);
{error, closed} ->
ok
end.
Java 客户端
public class Client {
public static void main(String[] args) {
Socket connection = new Socket("localhost", Port);
DataOutputStream output = new DataOutputStream(connection.getOutputStream());
Scanner sc = new Scanner(System.in);
while(true) {
output.writeBytes(sc.nextLine());
}
}
}
结果
客户
Hello!
服务器
Received: H
Received: el
Received: lo!
我一直在搜索,如果我理解正确,TCP不知道消息的大小,您需要手动设置某种分隔符。
但我不明白的是,如果我用 Erlang 编写客户端,消息似乎永远不会分开,如下所示:
Erlang 客户端
-module(client).
-export([start/1]).
start(Port) ->
{ok, Socket} = gen_tcp:connect({127,0,0,1}, Port, []),
loop(Socket).
loop(Socket) ->
gen_tcp:send(Socket, io:get_line("> ")),
loop(Socket).
结果
客户
Hello!
服务器
Received: Hello!
这让我想知道它是否可以在 Java 端修复?我在服务器端尝试了几种不同的输出流、写入方法和套接字设置的组合,但都没有解决问题。
此外,网络上有大量 Erlang(聊天)服务器示例,它们不做任何分隔符,尽管它们通常在两端都用 Erlang 编写。然而,他们似乎认为消息就像发送一样被接收。这只是不好的做法,还是当客户端和服务器都用 Erlang 编写时,是否有一些关于消息长度的隐藏信息?
如果需要分隔符检查,我很惊讶我找不到关于该主题的太多信息。如何以实际的方式完成?
提前致谢!
【问题讨论】: