2016-10-14 43 views
0

嗨,让我直接解决问题。我有一次在客户端进行身份验证Java tcp socket无法正常接收

但包回来以一种不可思议的方式,喜欢它的分裂或东西例如服务器发送给该客户一个很大的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(); 
      } 
     } 
    } 

感谢有一个美好的一天。

+0

尝试将ByteBuffer大小增加到2048. –

+0

我试过它的工作,但不适用于大数据包,我猜想某些代码需要完成更大的数据包。 – Premt

+0

试试这个:ByteBuffer.allocate(2048);在你的代码中 –

回答

1

喜还是让我开门见山的问题,所以我得到了,一旦客户端通过验证

你的意思是你有一个大JSON 消息服务器发送给该客户一个很大的JSON数据包。数据包是网络协议用来交换信息的东西。

但包回来像其拆分或东西比如奇怪的是:

除非你正在寻找的电线,你是不是在看包。您正在查看从TCP连接结束时获得的字节。

的JSON应该是:

收到:{ “用户ID”:1, “PlayerID”:2 “EXP”:0, “报警等级”:1, “硬币”:0,“ItemSlots “:30}

当涉及通过:

收到:{” 用户ID “:1,” PlayerID “:2”,EXP “:0,” 报警等级 “:1,” 硬币“:0, 收到:“ItemSlots”:30}

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

为什么当它涉及到客户端

这将邮件拆分数据包,因为这是TCP如何得到的消息,另一边是拆分包什么的。 TCP不是一个消息协议,它不知道或关心应用程序认为是什么消息 - 这是应用程序的工作。

以及我该如何解决这个问题?

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

TL; DR:如果你想要一个应用级消息协议,你需要实现一个。 TCP不是其中之一。

1

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

如果服务器发送1000字节数据,客户端应用程序可以在多个recv或单个recv上接收相同的数据。 TCP不保证任何行为。 “拆分”可能发生,这是由应用程序来处理数据进入多个块,将它合并到一个单位的应用程序数据进行进一步处理。人们可以在大数据量下看到这一点。

1

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

为什么当它涉及到客户端

最有可能的数据被分成两个或更多的数据包将其分割包什么的。

以及我该如何解决这个问题?

保持尽显你的缓冲区,直到套接字服务器关闭(read应该返回-1而不是0在这种情况下)。您需要为每个通道维护一个单独的缓冲区。如果服务器在发送数据后没有关闭它,则需要以其他方式描述;例如,您可以在JSON blob前添加大小标题。