NIO:写入的字节永远不会到达接收器

时间:2015-11-26 15:21:33

标签: java nio proc

我正在开发一个Java库来使用NIO交换数据。是否有可能我的客户端将某些东西写入套接字并关闭它,服务器接受连接但是从不读取那些字节,因为read方法返回-1?

在我的情况下是客户端在写入套接字后,关闭连接。我把这个问题的日志留在这里。正如您所看到的,379个字节写在套接字的客户端,但从未在服务器上收到。

客户端日志

43:32.335- OPENING SOCKET 1480207683
43:32.976- FINISH CONNECTION for socket@1480207683 -> Socket[addr=/10.20.0.10,port=43000,localport=45002]
43:32.976- Socket 1480207683 has written 379 bytes
43:33.445- Closing socket 1480207683

服务器日志

43:32.766: ACCEPT for socket@816266612 -> Socket[address=/172.16.8.251,port=45002,localPort=43000]
43:33.641 D/Comm: Socket 816266612 has read -1 bytes
43:33.644 D/Comm: Closing socket 816266612...

我有哪些选项可以确保此通信有效?我要等到服务器结束才关闭客户端?或者是否有任何其他方法可以确保一旦写入套接字,消息应该到达网络所做的任何事情?

以下是写入和读取方法的代码(我简化了它,因为它在接收到根本不感兴趣的字节后进行了一些处理)。它适用于我正在进行的99%的通信和简单的情况。处理许多并发通信时会出现问题。

private void read(SelectionKey key) {
    SocketChannel sc = (SocketChannel) key.channel();
    // Read data from the socket
    ByteBuffer readBuffer = ByteBuffer.allocate(NIOProperties.PACKET_SIZE);
    int size = sc.read(readBuffer);
    LOGGER.info("Socket " + sc.hashCode() + " has read " + size + " bytes");
    if (size == -1) {
        closeChannel(key, sc);
        return;
    }
    readBuffer.flip();
    process(readBuffer);
}

private void write(SelectionKey key) {
    if (writeBuffer != null) {
        if (writeBuffer.remaining() > 0) {
            int written = sc.write(writeBuffer);
            LOGGER.info("Socket " + sc.hashCode() + " has written " + written + " bytes");
        }
        changeInterest(sc, SelectionKey.OP_READ);          
    }
}

1 个答案:

答案 0 :(得分:1)

  

我的客户端是否有可能将某些东西写入套接字并关闭它,服务器接受连接但是从不读取这些字节,因为read方法返回-1?

没有。在read()返回-1之前将读取所有数据。 TCP保证它。

如果这是一个高并发性问题,我怀疑某些内容static不应该是static,或者是一个成员变量,它应该是一个局部变量。例如套接字通道,或选择键或缓冲区。

注意:您不需要将密钥传递给closeChannel()。你甚至不需要这种方法,除非它记录了一些东西。 channel.close()就足够了。