简体   繁体   English

Java TCP套接字无法正确接收

[英]Java tcp socket does not receive properly

Hi let me get straight to the problem. 嗨,让我直接解决这个问题。 I have a big JSON packet that the server sends to this client once the client is authenticated 客户端通过身份验证后,服务器会向该客户端发送一个大的JSON数据包

But the packet comes back in a weird way like it's split or something example: 但是数据包以一种奇怪的方式返回,例如被拆分或出现以下示例:

The JSON should be: JSON应该是:

Received: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0,"ItemSlots":30}

When it comes through: 通过时:

Received: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0,
Received: "ItemSlots":30}

Why does it split the packet or something when it comes to the client and how can I fix this anyway? 为什么要分割数据包或其他东西,如何解决客户端问题?

Java Receive Code: Java接收代码:

   private class ClientThread extends Thread {
        public void run() {
            try {
                while (selector.select() > 0) {
                    for (SelectionKey sk : selector.selectedKeys()) {

                        selector.selectedKeys().remove(sk);
                        if (sk.isReadable()) {

                            SocketChannel sc = (SocketChannel)sk.channel();
                            ByteBuffer buff = ByteBuffer.allocate(1024);
                            String content = "";

                            while (sc.read(buff) > 0) {
                                sc.read(buff);
                                buff.flip();
                                content += charset.decode(buff);
                                buff.clear();
                            }

                            System.out.println("Recieved: " + content);
                            sk.interestOps(SelectionKey.OP_READ);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Thanks have a wonderful day. 谢谢,祝你有美好的一天。

TCP protocol does not maintain message boundaries. TCP协议不维护消息边界。 It is not guaranteed that what the server sends is received as-is by the client and vice-versa. 不能保证服务器发送的内容是客户端原样接收的,反之亦然。

If the server sends 1000 bytes data, the client application can receive the same across multiple recv or single recv . 如果服务器发送1000字节的数据,则客户端应用程序可以跨多个recv或单个recv接收相同的数据。 TCP does not guarantee any behaviour. TCP不保证任何行为。 "Split" can happen, it is upto the application to handle the data coming in multiple chunks, coalesce it to one unit of application data for further processing. 可能会发生“拆分”,这取决于应用程序来处理来自多个块的数据,将其合并到一个单元的应用程序数据中以进行进一步处理。 One can see this particularly with large data sizes. 特别是对于大数据量,可以看到这一点。

It looks like you've got a non-blocking socket channel, meaning that the while (sc.read(buff) > 0) { loop is terminating due to sc.read(buff) returning 0 since only a portion of the data sent has, at this point, been received. 看起来您有一个无阻塞的套接字通道,这意味着while (sc.read(buff) > 0) {循环因sc.read(buff)返回0而终止,因为仅发送了一部分数据至此,已经收到。

Why does it split the packet or something when it comes to the client 为什么要拆分数据包之类的东西?

Most likely the data is being split into two or more packets. 数据很可能被拆分为两个或更多数据包。

and how i can i fix this anyway? 以及我该如何解决呢?

Keep filling your buffer until the socket is closed by the server ( read should return -1 rather than 0 in that case). 继续填充缓冲区,直到服务器关闭套接字为止(在这种情况下, read应该返回-1而不是0)。 You need to maintain a separate buffer per channel. 您需要为每个通道维护一个单独的缓冲区。 If the server doesn't close its end after sending the data, you'll need to delineate in some other way; 如果服务器在发送数据后没有关闭其末端,则需要以其他方式进行描述。 you could prefix the JSON blob with a size header, for instance. 例如,您可以在JSON blob的前面加上大小标头。

Hi lemme get straight to the problem so i got a big JSON packet that the server sends to this client once the client is authenticated 嗨lemme直接解决了这个问题,所以我获得了一个大的JSON数据包,一旦客户端通过身份验证,服务器就会发送到该客户端

You mean you have a big JSON message . 您的意思是您有一条很大的JSON 消息 Packets are things that network protocols used to exchange information. 数据包是网络协议用来交换信息的事物。

But the packet comes back in a weird way like its split or something example: 但是数据包以一种奇怪的方式返回,例如拆分或类似的例子:

Unless you're looking at the wire, you aren't looking at packets. 除非您查看电线,否则您不会查看数据包。 You're looking at the bytes you got from your end of the TCP connection. 您正在查看从TCP连接结束获得的字节数。

The JSON should be: JSON应该是:

Recieved: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0,"ItemSlots":30} 已接收:{“ UserID”:1,“ PlayerID”:2,“ EXP”:0,“ Lvl”:1,“ Coins”:0,“ ItemSlots”:30}

When it comes through: 通过时:

Recieved: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0, Recieved: "ItemSlots":30} 已接收:{“ UserID”:1,“ PlayerID”:2,“ EXP”:0,“ Lvl”:1,“硬币”:0,已接收:“ ItemSlots”:30}

Excellent. 优秀的。 You got the same bytes. 您得到了相同的字节。 Now make a JSON parser that figures out where the message ends and parses it. 现在创建一个JSON解析器,以弄清消息的结尾并对其进行解析。

Why does it split the packet or something when it comes to the client 为什么要拆分数据包之类的东西?

It splits the message into packets because that's how TCP gets the message to the other side. 它将消息拆分为数据包,因为这就是TCP将消息发送到另一端的方式。 TCP is not a message protocol and it doesn't know or care what the application considers to be a message -- that's the application's job. TCP不是消息协议,它不知道或不在乎应用程序认为什么是消息,这就是应用程序的工作。

and how i can i fix this anyway? 以及我该如何解决呢?

Write a JSON parser to figure out where the messages end. 编写JSON解析器以找出消息的结尾。 You haven't implemented any code to receive JSON over TCP yet, so that won't work until you do. 您尚未实现任何代码来通过TCP接收JSON,因此直到您这样做才起作用。

TL;DR: If you want an application-level message protocol, you need to implement one. TL; DR:如果需要应用程序级消息协议,则需要实现一个。 TCP is not one. TCP不是一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM