我正在开发一个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);
}
}
答案 0 :(得分:1)
我的客户端是否有可能将某些东西写入套接字并关闭它,服务器接受连接但是从不读取这些字节,因为read方法返回-1?
没有。在read()
返回-1之前将读取所有数据。 TCP保证它。
如果这是一个高并发性问题,我怀疑某些内容static
不应该是static
,或者是一个成员变量,它应该是一个局部变量。例如套接字通道,或选择键或缓冲区。
注意:您不需要将密钥传递给closeChannel()
。你甚至不需要这种方法,除非它记录了一些东西。 channel.close()
就足够了。