Erlang服务器,Java客户端-TCP消息被拆分了吗?

卡尔格伦

如标题所示,我有一个用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编写客户端和服务器时是否存在一些有关消息长度的隐藏信息?

如果需要进行定界符检查,我很惊讶我找不到关于此主题的太多信息。如何以实用的方式完成?

提前致谢!

保罗·盖奥特

您需要在服务器和客户端之间定义协议,以将TCP流拆分为消息。TCP流分为数据包,但不能保证这些数据包与您的发送/写入或接收/读取调用相匹配。

一个简单而强大的解决方案是为所有消息添加一个长度。Erlang可以使用{packet, 1|2|4}选项透明地执行此操作,其中前缀以1、2或4个字节编码。您将必须在Java端执行编码。如果选择2或4个字节,请注意长度应以big-endian格式编码,DataOutputStream.outputShort(int)DataOutputStream.outputInt(int)Java方法使用的字节顺序相同

但是,从您的实现看来,您确实有一个隐式协议:您希望服务器单独处理每一行。

幸运的是,Erlang也对此进行了透明处理。您只需要传递{packet, line}选项。但是,您可能需要调整接收缓冲区,因为该缓冲区将被截断更长的行。这可以通过{recbuf, N}选项来完成

因此,只需重新定义选项即可完成您想要的操作。

-define(MAX_LINE_SIZE, 512).
-define(TCP_OPTIONS, [list, {packet, line}, {active, false}, {reuseaddr, true}, {recbuf, ?MAX_LINE_SIZE}].

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

TCP服务器和客户端Java

来自分类Dev

TCP服务器和客户端Java

来自分类Dev

Java TCP 客户端/服务器套接字

来自分类Dev

TCP 服务器未收到来自 TCP 客户端的消息 (Java)

来自分类Dev

Java TCP 服务器无法接收来自多个客户端的消息

来自分类Dev

让TCP客户端搜索TCP服务器

来自分类Dev

让TCP客户端搜索TCP服务器

来自分类Dev

Java(客户端)和C#(服务器)TCP套接字。和服务器从客户端读取无限的最后数据

来自分类Dev

消息未从服务器发送到单个服务器中的客户端-Java中的多个客户端

来自分类Dev

消息未从服务器发送到单个服务器中的客户端-Java中的多个客户端

来自分类Dev

使用 gen_tcp 的 Erlang 客户端-服务器示例未收到任何信息

来自分类Dev

监督gen_tcp客户端/服务器

来自分类Dev

TCP客户端-服务器程序的问题

来自分类Dev

XmlSerializer和NetworkStream与Tcp服务器-客户端

来自分类Dev

c#从服务器ping TCP客户端

来自分类Dev

TCP / IP服务器客户端

来自分类Dev

TCP高CPU多客户端服务器

来自分类Dev

TCP / IP服务器客户端

来自分类Dev

使用g ++的TCP服务器客户端

来自分类Dev

Unity TCP服务器/客户端

来自分类Dev

TCP服务器客户端大json

来自分类Dev

从TCP服务器踢客户端

来自分类Dev

TCP客户端到服务器损坏数据

来自分类Dev

c#从服务器ping TCP客户端

来自分类Dev

Tornado TCP服务器/客户端进程通信

来自分类Dev

如何让 TCP 服务器处理多个客户端?

来自分类Dev

Python、TCP、服务器和客户端

来自分类Dev

服务器无法向客户端发送消息

来自分类Dev

服务器向客户端发送消息