Java NIO TCP超时问题

时间:2015-05-01 04:15:59

标签: java multithreading tcp nio socketchannel

我在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方法,但因为read操作只是阻塞,所以此方法不起作用。有没有其他方法可以检测连接丢失而不在新线程中使用心跳?

如果连接丢失,是否可能在写入/读取时抛出错误?

提前致谢。

编辑:

主题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块。最后关闭socketchannel。

sendPacket:

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

receivePacket:

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模块。

2 个答案:

答案 0 :(得分:1)

  

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

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

,编写正确的非阻塞NIO代码相当困难
  

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

不,不。你处于非阻塞模式。它要么返回一个正整数,要么返回0,否则抛出异常。这是什么?

  

我尝试在线程2中使用heartbeat方法,但因为read操作只是阻塞,所以这个方法不起作用。

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

  

是否有其他方法可以在不使用新线程中的心跳的情况下检测连接丢失?

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

  

如果连接丢失,是否可能在写入/读取时抛出错误?

这就是发生的事情。

这个问题存在严重问题。您发布的代码不是真实代码,也不符合您的描述。您需要发布更多内容,例如你的读写代码。

答案 1 :(得分:0)

您可以在套接字上查找启用TCP-KEEP alive选项。在空闲连接keep-alive消息被发送并且预期TCP层的那些消息。

如果TCP-KEEP活动失败,则下一次读/写操作将导致错误(ECONNRESET),可用作连接丢失的标志。