socket的InputStream没有关闭同伴丢失

时间:2017-03-28 12:55:01

标签: java sockets tcp inputstream

我正在连接打开插座的设备 要获取传入数据,我会在另一个帖子中对read执行InputStream操作 当我拿走我连接的对等设备的电量时,我的InputStream无法识别连接丢失。

这是我等待输入的代码:

StringBuilder sb = new StringBuilder();
String result = "";
int c;
try
{
  log.info( "waiting for data..." );
  while ( ( ( c = inputStream.read() ) >= 0 ) )
  {
    if ( c == -1 )
    {
      log.info( "is -1" );
    }
    /*
     * TODO: <LF> Can't always be the delimiter to define the end of an message. This should be
     * parameterized.
     */
    if ( c == 0x0a /* <LF> */ )
    {
      result = sb.toString();
      sb.delete( 0, sb.length() );
    }
    else if ( c != 0x0d /* <CR> */ )
    {
      sb.append( (char) c );
    }
    if ( !result.isEmpty() )
    {
      log.info( getName() + ": received message: " + result );
      listener.MessageReceived( result.getBytes() );
      result = "";
    }
  }
  log.info( "stream ended" );
  disconnect();
  listener.closed();
}
catch ( IOException | ResourceException e )
{
  try
  {
    log.info( "in catch block" );
    disconnect();
    listener.closed();
    throw new ResourceException( "An error occured during the receiving of a message for the device, or connection timed out.", e );
  }
  catch ( ResourceException e1 )
  {
    e1.printStackTrace();
  }
}

如果该信息可用于任何情况,则它位于JCA连接器内部。 据我所知,当Stream被中断时,InputStream会收到-1,通常他应该跳转到我的stream ended日志但不会发生。

为什么它不能识别连接无法使用,因为远程对等设备已关闭?

2 个答案:

答案 0 :(得分:2)

正如您所说,您不希望超时,因为即使它没有发送数小时,您也需要等待对等方。除非采取特殊措施,否则不会发送数小时的同伴和已关闭的同伴之间没有区别。只要没有发送数据包,就无法检测到差异。

您可以做一件事来确保发送数据包:您可以使用Socket.setKeepAlive(true)方法打开SO_KEEPALIVE套接字选项。

问题在于您无法从Java控制保持活动探针的发送频率。这通常取决于操作系统内核中的设置。 尽管如此,它仍然可以让您比“永远”更快地检测到死亡(或无法到达)的同伴。

答案 1 :(得分:1)

@读取超时,正如@Kayaman所建议的那样,是实现心跳的常用方法。你需要一个'timingOut'布尔值,初始化为false。每当收到任何数据,数据或心跳轮询回复时,将其设置为false。读取超时后,检查'timingOut'标志。如果为false,则发送轮询请求并将'timingOut'设置为true。如果为true,请关闭套接字并执行“连接丢失”操作。

不需要单独的线程。如果经常传输数据,不要浪费轮询。