Java NIO套接字通道发送和接收字节大小不匹配

时间:2018-03-14 17:16:47

标签: java nio socketchannel

我有服务器和客户端。 服务器使用以下方式发送数据:

private int writeMessage(AgentHandler agentHandler, Msg message) {
    SocketChannel sc = agentHandler.getSocketChannel();
    byte[] encodedMessage = Encoder.INSTANCE.encode(message);
    ByteBuffer writeBuffer = ByteBuffer.wrap(encodedMessage);
    int count = 0;
    while (writeBuffer.hasRemaining()) {
        try {
            int written = sc.write(writeBuffer);
            count += written;
        } catch (IOException e) {
            deregisterAgent(agentHandler.getAgentID());
        }
    }
    System.out.printf("Written bytes: %s\n", count);
    return count;
}

我有输出:

  

书面字节:31904

客户端使用下一段代码接收数据:

private void readFromSockets() {
    int readReady = 0;
    try {
        readReady = readSelector.select();
    } catch (IOException e) {
        e.printStackTrace();
    }
    if (readReady > 0) {
        Set<SelectionKey> selectedKeys = readSelector.selectedKeys();
        Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

        while (keyIterator.hasNext()) {
            SelectionKey key = keyIterator.next();
            if (key.isReadable())
                readFromSocket(key);
            keyIterator.remove();
        }
        selectedKeys.clear();
    }
}



private void readFromSocket(SelectionKey key)  {
    ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);
    SocketChannel socketChannel = (SocketChannel) key.channel();
    int counter = 0, bytesRead;
    try {
        while ((bytesRead = socketChannel.read(byteBuffer)) != 0) {
            if (bytesRead == -1) {
                System.out.println("Socket channel seems disconnected.");
                try {
                    socketChannel.close();
                    return;
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
            counter += bytesRead;
            System.out.println("reading from socket...");
        }

    } catch (IOException e) {
        System.out.println("Socket Channel IO exception catched");
        try {
            socketChannel.close();
            return;
        } catch (IOException e1) {
            e1.printStackTrace();
            return;
        }
    }
    System.out.println("Bytes received " + counter);

    byteBuffer.flip();
    byte[] message = new byte[counter];
    byteBuffer.get(message, 0, counter);
    Msg incomingMessage = Encoder.INSTANCE.decode(message);
    if (incomingMessage != null) {
        processMessage(incomingMessage);
    }
}

和客户端输出

  

字节收到14828

此问题只能在真正远程连接的情况下表示(在我的情况下,在其他国家/地区的服务器和客户端)。

当我在localhost上测试我的代码时,我没有问题。

我需要建议如何解决这个问题。

1 个答案:

答案 0 :(得分:0)

听起来你在数据流中遇到了暂时的缺口。如果你只是继续阅读,你最终会得到所有的消息字节。不幸的是,根据您当前的设置,您无法确定何时到达消息的末尾,是否还有更多字节,或者您是否已收到下一条消息的一部分!

通过套接字写出消息中的字节数,然后是消息本身。读取时,读取消息长度,然后读取消息字节,直到读取完整的消息。