[vert.x] Vertx TCP套接字在快速写入时读取部分消息

时间:2018-08-13 15:14:18

标签: java sockets vert.x

我正在尝试构建一个实时应用程序,一次发送和接收信息分配。我设法使Vertx套接字服务器和客户端正常工作,但是我面临一个问题。当我有大量数据要一次写入约1000条记录时,缓冲区似乎读取速度太快,并且部分读取了当前消息之前的消息,例如,如果我发送了两条消息

  

消息1“ hello world”

     

消息2“我在这里”

然后套接字将收到

  

“你好,我是世界”,然后它将收到“这里”

,但是它应该分别接收这些字符串。我该如何强制套接字一次仅接收一条消息,就像HTTP客户端使用其request.bodyHandler方法所做的那样。在这方面的任何帮助将不胜感激。

这是我的服务器代码

NetServerOptions options = new NetServerOptions();
    options.setReceiveBufferSize(max_buffer_size);
    options.setSendBufferSize(max_buffer_size);
    NetServer server = vertx.createNetServer(options);
    server.exceptionHandler(e -> {
        Debug.log("Client exception " +e.toString()); 
    });


    server.connectHandler(socket -> {
        socket.exceptionHandler(e -> {
            Debug.log("Client socket exception " + e.toString());
        });
        String host = socket.localAddress().host();

        Buffer totalBuffer = Buffer.buffer();
        socket.handler(buffer -> {
            Debug.log("data ::" + buffer.toString());
            final RecordParser parser = RecordParser.newDelimited(delemeter, h -> {
                Debug.log("data SPLIT ::::::::" + h.toString());
                handler.HandleUpdate(h.toString(), socket);
            });
            parser.handle(buffer);
        });
    });

这是我的客户代码:

NetClientOptions options = new NetClientOptions()
            .setConnectTimeout(this.connection_timeout)
            .setReconnectAttempts(this.connection_attempts)
            .setReconnectInterval(this.connection_reconnect_delay)
            .setReceiveBufferSize(max_buffer_size)
            .setSendBufferSize(max_buffer_size);

    NetClient client = this.vertx.createNetClient(options);
    client.connect(this.port, ip, res -> {
        if (res.succeeded()) {
            System.out.println("Connected!");
            this.client_socket = res.result();

            Buffer totalBuffer = Buffer.buffer();
            this.client_socket.handler(buffer -> {
                    Debug.log("data ::" +buffer.toString()); 
                handler.HandleUpdate(buffer.toString(), null);
            });

        } else {
            System.out.println("Failed to connect: " + res.cause().getMessage());
        }
    });

2 个答案:

答案 0 :(得分:0)

问题是您没有用于正确识别不同消息的TCP协议,并且与Vert.x不相关。您将在其他任何客户端/服务器上遇到相同的问题。

例如,您需要一种识别消息的方法

  • 在邮件中使用长度前缀编码,例如长11 +“ Hello World”
  • 使用分隔符,例如“ Hello World \ n”,其中\ n是字符分隔符

通过这种方式,解码器可以正确解码消息。

如果您查看HTTP / 1协议,它就是这样做的,例如分块的编码消息:

PUT /foo HTTP/1.1\r\n Transfer-encoding: chunked\r\n \r\n 11\r\n Hello World\r\n 0\r\n \r\n

这使用了之前介绍的两种技术。

答案 1 :(得分:0)

您的错误只是对lambda的误解

您只需要更换

socket.handler(buffer -> {
    Debug.log("data ::" + buffer.toString());
    final RecordParser parser = RecordParser.newDelimited(delemeter, h -> {
        Debug.log("data SPLIT ::::::::" + h.toString());
        handler.HandleUpdate(h.toString(), socket);
    });
    parser.handle(buffer);
});

通过类似

socket.handler(
    RecordParser.newDelimited(delemeter, h -> {
        Debug.log("data SPLIT ::::::::" + h.toString());
        handler.HandleUpdate(h.toString(), socket);
    })
});

在第一个方法中,每次您从套接字收到消息时都创建一个新的实例解析器。您将在第二个代码中创建一个解析器实例,该实例将接收每个缓冲区并正确解析块。