Java tcp套接字无法正常接收

时间:2016-10-14 17:02:44

标签: java json sockets tcp

嗨,让我直接解决问题。我有一个很大的JSON数据包,一旦客户端通过身份验证,服务器就会发送给该客户端

但是数据包以一种奇怪的方式回归,就像它的分裂或者其他一些例子一样:

JSON应该是:

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

当它出现时:

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

为什么它会分组数据包或其他什么来到客户端,我怎么能解决这个问题呢?

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();
            }
        }
    }

谢谢你度过了美好的一天。

3 个答案:

答案 0 :(得分:1)

TCP协议不维护消息边界。无法保证客户端按原样接收服务器发送的内容,反之亦然。

如果服务器发送1000字节数据,则客户端应用程序可以跨多个recv或单recv接收相同的数据。 TCP不保证任何行为。 "分流"可能发生这种情况,应用程序处理来自多个块的数据,将其合并到一个应用程序数据单元以进行进一步处理。人们可以看到这一点,尤其是大数据量。

答案 1 :(得分:1)

看起来你有一个非阻塞套接字通道,这意味着while (sc.read(buff) > 0) {循环因sc.read(buff)返回0而终止,因为只发送了一部分数据,这一点,已被收到。

  

为什么它会在客户端

时拆分数据包

很可能数据被分成两个或多个数据包。

  

我怎么能解决这个问题?

继续填充缓冲区,直到服务器关闭套接字(read应返回-1而不是0)。您需要为每个通道维护一个单独的缓冲区。如果服务器在发送数据后没有关闭其结束,您需要以其他方式描述;例如,您可以使用大小标头为JSON blob添加前缀。

答案 2 :(得分:1)

  

嗨lemme直接解决问题所以我得到了一个大的JSON数据包,服务器在客户端通过身份验证后发送给该客户端

你的意思是你有一个很大的JSON 消息。数据包是网络协议用于交换信息的东西。

  

但是数据包以一种奇怪的方式回归,就像它的分裂或者一些例子一样:

除非您正在查看电汇,否则您不会查看数据包。您正在查看从TCP连接结束时获得的字节数。

  

JSON应该是:

     

接收:{" UserID":1," PlayerID":2," EXP":0," Lvl":1, "硬币":0," ItemSlots" 30}

     

当它出现时:

     

接收:{" UserID":1," PlayerID":2," EXP":0," Lvl":1, "硬币":0,   收到:" ItemSlots":30}

优异。你有相同的字节。现在创建一个JSON解析器,找出消息结束的位置并解析它。

  

为什么它会在客户端

时拆分数据包

它将消息拆分为数据包,因为TCP是如何将消息传递给另一方的。 TCP不是消息协议,它不知道或不关心应用程序认为是消息的内容 - 这是应用程序的工作。

  

我怎么能解决这个问题?

编写JSON解析器以确定消息的结束位置。您还没有实现任何代码来通过TCP接收JSON,所以在您这样做之前不会工作。

TL; DR:如果您需要应用程序级消息协议,则需要实现一个。 TCP不是一个。