Java NIO TCP超时问题

Java NIO TCP timeout issue

我在 2 个线程中使用一个 SocketChannel,一个线程用于发送数据,另一个线程用于接收数据。

SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(ip,port));
socketChannel.configureBlocking(false);

线程1:使用上面的socketchannel写数据

线程2:使用同一个socketchannel读取数据

我没有在 socketchannel 中使用任何选择器,因为我需要异步写入和读取(使用 2 个不同的线程)

问题:当连接丢失时,socketchannel.write() 和 socketchannel.read() 操作不会抛出任何错误。它只是阻止操作。

我需要检测连接丢失。

我尝试在线程2中使用heartbeat方法,但是因为读取操作只是阻塞,所以这个方法不起作用。有没有其他方法可以在不使用新线程中的心跳的情况下检测连接丢失?

如果连接丢失,writing/reading是否可能抛出错误?

提前致谢。

编辑:

线程 1:

public void run() {
  socketChannel = SendAndReceivePacketUtil.createConnection(ip, port);
  socketChannel.configureBlocking(false);

  RecTask task = new RecTask(socketChannel);
  Thread recThread = new Thread(task);
  recThread.start();

  while(true)
  {
     byte[] data= getDataFromQueue(ip);
     if(data!= null) {
         //print(new String(data));
         sendPacket(data, socketChannel);
     }
   }
}

线程 2:(RecTask)

public void run() {
  while(true) {
    byte[] data = receivePacket(socketChannel);
    //print(new String(data));
  }
}

线程 1 和 2 都有 try-catch-finally 块。最后关闭套接字通道。

发送数据包:

int dataSent = 0;
while (dataSent < data.length) {
    long n = socketChannel.write(buf);
        if (n < 0) {
            throw new Exception();
        }
        dataSent += (int) n;
 }

接收数据包:

int dataRec = 0;
byte[] data = new byte[length];
ByteBuffer buffer = ByteBuffer.wrap(data);

while (dataRec < length) {
    long n = socketChannel.read(buffer);
    if (n < 0) {
        throw new Exception();
    }
    dataRec += (int) n;
}       
return data;

我不断地发送和接收数据。但是一旦连接丢失,就不会打印任何内容,代码就会卡住。它是一个 android wifi 直接应用程序。对于连接丢失的情况,我只是关闭 wifi 模块。

您可以在套接字上寻找启用 TCP-KEEP 活动选项。在空闲连接上发送 keep-alive 消息,并且预期 TCP 层的消息会收到 ACK。

如果 TCP-KEEP alive 失败,您的下一个 read/write 操作将导致错误 (ECONNRESET),这可以用作连接丢失的标志。

I am not using any selectors with the socketchannel as I need the write and read to be asynchronous (using 2 different threads)

这不是避免 Selector. 的理由事实上,没有 Selector.

就很难编写正确的非阻塞 NIO 代码

PROBLEM: When the connection is lost, the socketchannel.write() and socketchannel.read() operation does not throw any error. It just blocks the operation.

不,不是。您处于非阻塞模式。它要么 returns 一个 post 个整数,要么为零,要么抛出异常。是哪个?

I tried using the heartbeat method in Thread 2 but because the read operation just blocks, this method did not work.

读操作在非阻塞模式下不阻塞。

Is there any other way to detect the connection loss without using the heartbeat in a new Thread?

检测 TCP 连接丢失的唯一可靠方法是写入连接。最终这将抛出 IOException: connection reset. 但由于缓冲、重试等原因,它不会在连接丢失后第一次发生

Is it possible to throw error while writing/reading if there is connection loss?

就是这样。

这个问题有严重的错误。您 post 编辑的代码不是真正的代码,或者它的行为与您描述的不一样。你需要 post 更多,例如你的读写代码。