Java 客户端向服务器发送部分消息,尽管显示为完整消息

标签 java tcpclient

我有一个用 Java 编写的客户端和一个用 C++ 编写的服务器。客户端在收到服务器的响应后,应该每 5 秒发送一条类似“MESSAGE|1|2|3|4|5”的消息。

开始连接:

private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream output = null;
private BufferedReader br = null;
private Timer timer;

public void start() 
{
    int timerRate = 5;

    try
    {
        int refreshRate = Integer.parseInt(appSingleton.getRefreshRateShared());
        timerRate = refreshRate;
    }
    catch(NumberFormatException e)
    {
        LOGGER.addLogError("Error converting refresh rate: "+e);
    }

    try
    {
        // Create socket and streams
        socket = new Socket(appSingleton.getIpAddressFullShared(), appSingleton.getIpPortShared());
        input = new DataInputStream( socket.getInputStream());
        output = new DataOutputStream( socket.getOutputStream());

        // Start Timer thread
        executorService = Executors.newSingleThreadScheduledExecutor();

        executorService.scheduleAtFixedRate(new Runnable() 
        {
            @Override
            public void run() 
            {
                // Create new TCP connection if the map is not currently updating
                if(isMapUpdating == false)
                {
                    isMapUpdating = true;

                    communicateWithServer();
                }
            }
        }, 0, timerRate, TimeUnit.SECONDS);
    }
    catch (UnknownHostException e)
    {
        cancelConnection();
    }

    catch (EOFException e)
    {
        cancelConnection();
    }

    catch (IOException e)
    {
        cancelConnection();
    }
}

public void communicateWithServer()
{
    // Create a message to the server
    String messageToServer = makeMessageToServer(); 
    String messageFromServer = connectToClient(messageToServer);

    // Read the message and update panel on the main thread
    SwingUtilities.invokeLater(() ->
    {
        messageReceived(messageFromServer);
    });
}

public String connectToClient(String messageToServer)
{
    String data = "";
    // Message from the server that should terminate TCP connection
    String  terminator = "END_DATA";

    try 
    {
        //Send message to the server
        output = new DataOutputStream( socket.getOutputStream());
        output.writeBytes(messageToServer);

        System.out.println("OUTPUT LENGTH: "+output.size());

        //Read Response
        br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String s = "";
        int value;

        // Process the message from the server and add to the StringBuilder
        while((value = br.read()) != -1) 
        {
            // converts int to character
            char c = (char)value;

            sb.append(c);

            if(sb.toString().contains(terminator))
            {
                break;
            }
        }

        // Create the final string
        data = sb.toString();
    } 
    catch (IOException e) 
    {
        cancelConnection();
        data = "ERROR";
    }

    return data;
}

private void messageReceived(String message)
{
    // Processing data from server and displaying values on Main Thread

    // Map finished updating when data is processed
    isMapUpdating = false;
}

服务器从客户端获取消息,将其转换为数组,然后进一步处理数据。第一条消息发送得很好。然而,在第二条消息时,服务器崩溃了。我检查了发送到服务器的内容,结果发现消息是这样的:

“消息|1|2|3|4|5”

“M”

“ESSAGE|1|2|3|4|5”

因此,服务器在收到第二条消息时崩溃,因为它无法将其拆分为数组。

当我检查 DataOutputStream 时,它总是显示正确的大小。

如果有人知道如何解决它,我们将不胜感激!

最佳答案

好吧,如果你要编写网络软件,双方都需要能够处理数据可能是碎片化的并一 block 一 block 地到达;您通常无法完全控制这一点。

不过,为了降低风险,请在写入输出流后刷新它:

    output = new DataOutputStream( socket.getOutputStream());
    output.writeBytes(messageToServer);
    output.flush();

它告诉流将缓冲数据写入下一层。

关于Java 客户端向服务器发送部分消息,尽管显示为完整消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49222046/

相关文章:

java - 组合框单元格编辑器的背景颜色

c# - 读取 TcpClient 实例上的 Connected 属性时出现异常

c# - 将数据从服务器发送回客户端

java - java GUI 帮助 - 主线程中有错误

java - 将编码对象写入文件

C#多线程文件传输使用TCP

java - Java Socket shutdownOutput 和 shutdownInput 是否负责 "Duplicate ACK #: 1"

sockets - 自动重新连接套接字客户端的设计选择

java - Spring JMS(ActiveMQ)延迟传递消息

java - JSF组件的动态值绑定(bind)