当前位置: 首页 > 知识库问答 >
问题:

JavaNIO TCP超时问题

袁法
2023-03-14

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

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

线程1:使用上述socketchannel写入数据

线程2:使用相同的socketchannel读取数据

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

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

我需要检测连接丢失。

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

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

提前谢谢。

编辑:

线程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:(矩形任务)

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

两个线程1

发送包:

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 direct应用程序。对于连接丢失场景,我只需关闭wifi模块。

共有2个答案

商宏爽
2023-03-14

您可以在套接字上查找启用TCP-KEEP活动选项。在空闲连接上,发送消息并为TCP层的消息发送确认字符。

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

西门威
2023-03-14

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

这不是避免使用选择器的原因

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

不,它没有。您处于非阻塞模式。它要么返回一个正整数,要么返回零,要么抛出一个异常。是哪一个?

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

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

有没有其他方法可以在新线程中不使用心跳来检测连接丢失?

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

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

事情就是这样。

这个问题有严重的问题。要么您发布的代码不是真正的代码,要么它的行为不像您描述的那样。您需要发布更多,例如您的读写代码。

 类似资料:
  • 问题内容: 我在gunicorn + nginx上运行django。我在上传文件时遇到了问题。实际上,上传工作正常,但gunicorn超时,因此在nginx中造成了这种情况: 如果刷新页面,可以看到所有照片都已上传。问题在于,这会导致超时,从而给人留下无法上传的印象。 这是我的gunicorn conf: 我尝试更改超时,但是没有用。 问题答案: 你可以尝试通过添加以下内容来升级Nginx中的代理

  • osx和Win的文档中写道:“对于TCP套接字,返回值0表示对等方关闭了连接的一半。” 2)阻塞套接字的问题:在阻塞套接字上,我希望SO_RCVTIMEO和SO_SNDTIMEO有一个默认值,比如30秒(用getsockopt检查)。但是为什么它们被设置为0?

  • 问题内容: 我有一个Web应用程序,它充当运行非常长任务的非现场服务器的接口。用户输入信息并点击提交,然后chrome等待响应,并在接收到新页面时加载它。但是,根据网络和用户的输入,任务可能会花费相当长的时间,并且在返回数据之前(尽管任务仍在运行),chrome有时会加载“无数据接收页”。 有没有办法在我的任务正在思考时放置一个临时页面,或者只是强制chrome继续等待?提前致谢 问题答案: 尽管

  • 有什么想法吗? 谢谢

  • 我有一个数十万对象的列表。当每一个运行时,它都会根据给定的值执行一个可能很长的计算。正因为如此,我希望异步运行每个任务(最好是通过使用某种执行器),并在30秒后检索每次计算的结果,取消那些没有及时完成的结果。(所得值在其他地方使用。) 到目前为止,我就是这样实现它的: ArrayList存储每个要执行的,然后将其发送到ExecutorService以运行所有任务。我遇到的问题是,任务似乎是同步启动

  • 问题内容: 我有一个Web应用程序,它充当运行非常长的任务的非现场服务器的接口。用户输入信息并点击提交,然后chrome等待响应,并在接收到新页面时加载它。但是,根据网络和用户的输入,任务可能会花费相当长的时间,并且在返回数据之前(尽管任务仍在运行),chrome有时会加载“无数据接收页”。 有没有办法在我的任务正在思考时放置一个临时页面,或者只是强制chrome继续等待?提前致谢 问题答案: 尽