首页 > 解决方案 > TCP客户端和服务器之间更好的通信方式

问题描述

我有一个命令系统来在我的 TCP 服务器和客户端 (Java) 之间进行通信。我可以向我的客户端发送特定的命令,如果客户端收到命令,它将执行某些操作。

基本上,这行得通。但有时我必须发送命令+额外信息。问题是:信息有时会发送得太快。所以一些信息会丢失/混淆,我的客户无法正确执行请求。我的解决方案是使用Thread.sleep(),但这既不干净也不有效。因为仍然存在无法正确接收信息的风险。

我的服务器:

public void sendCommand(Socket socket) throws InterruptedException, IOException {
    writeMsg("CMD_POPUP", socket);
    Thread.sleep(150);
    writeMsg("foo", socket);
    Thread.sleep(150);
    writeMsg("bar", socket);
    Thread.sleep(150);
    writeMsg("baz", socket);
}

public void writeMsg(String message, Socket socket) throws IOException {
    DataOutputStream out = new DataOutputStream(socket.getOutputStream());
    out.writeUTF(message);
}

我的客户:

public void interpreteCommand(Socket socket) throws IOException {
    while (true) {
        switch (readMsg(socket)) {
            case "CMD_POPUP":
                System.out.println(readMsg(socket)); 
                System.out.println(readMsg(socket)); //Sometimes it would be 'bar' but also sometimes it would be 'baz'
                System.out.println(readMsg(socket)); //Sometimes it would be 'baz' but also sometimes it would be nothing
                break;
        }
    }
}

public String readMsg(Socket socket) throws IOException {
    DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    return in.readUTF();
}

标签: javasocketsnetworkingtcp

解决方案


首先,我不是java程序员。但是 tcp 连接在其他编程语言中的工作方式相同。

TCP 连接是基于流的,这意味着消息没有开始或结束。TCP 唯一能保证的是数据以正确的顺序到达。

如果你紧接着发送“CMD_POPUP”和“foo”,不知道对方是否会收到“CMD_POPUP”、“CMD_POPUPfoo”、“CMD_PO”等。因为您在每次发送之间等待特定的时间,所以数据通常一个接一个地到达。但这并不能保证,我也认为这是一种不太干净的方法。

解决这个问题的最简单方法是在开头发送一个开始字符,在参数之间发送分隔符,在每条消息之后发送一个结束字符。例如“#CMD_POPUP%foo%bar$”或类似的东西。这样,您可以将收到的所有内容写入缓冲区,直到收到消息的结尾,然后处理它。


推荐阅读