【问题标题】:what causes : java.net.SocketException: Connection timed out, Not the SocketTimeoutException什么原因:java.net.SocketException:连接超时,而不是 SocketTimeoutException
【发布时间】:2012-01-18 02:41:37
【问题描述】:

ObjectInputStream.readObject()方法抛出了这个SocketException,是什么原因导致这个异常?另外,客户端和服务端socket的soTimeout的值都为0,KeepAlive的值为false。

{2012-01-09 17:44:13,908} ERROR java.net.SocketException: Connection timed out
 at java.net.SocketInputStream.socketRead0(Native Method)
 at java.net.SocketInputStream.read(SocketInputStream.java:146)
 at sun.security.ssl.InputRecord.readFully(InputRecord.java:312)
 at sun.security.ssl.InputRecord.read(InputRecord.java:350)
 at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:809)
 at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:766)
 at sun.security.ssl.AppInputStream.read(AppInputStream.java:94)
 at sun.security.ssl.AppInputStream.read(AppInputStream.java:69)
 at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2265)
 at java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:2558)
 at    java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2568)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1314)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)

从关于setSoTimeout方法的JAVA API文档中,如果该方法设置了一个非零值,当times过期时,只会抛出SocketTimeoutException,而不是SocketException:Connection timed out,所以,这个异常应该不相关使用 setSotimeoutMethod。

public void setSoTimeout(int timeout)  throws SocketException
 Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this 
 option set to a non-zero timeout, a read() call on the InputStream associated with 
 this Socket will block for only this amount of time. If the timeout expires, a 
 java.net.SocketTimeoutException is raised, though the Socket is still valid. The 
option must be enabled prior to entering the blocking operation to have effect. The 
timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.

但是PlainSocketImpl(here,is SSLSocketImpl).getTimeout()返回的值是通过setSoTimeout()方法传过来的,那么还是一个很奇怪的方法。

 SocketInputStream.socketRead0(FileDescriptor fd, byte b[], int off, int len, int timeout)  
  the timeout value is passed in the constructor of  SocketInputStream:SocketInputStream(PlainSocketImpl impl) throws IOException {}
  timeout = impl.getTimeout();

【问题讨论】:

    标签: sockets objectinputstream


    【解决方案1】:

    java.net.SocketException:连接超时异常与setTimeout方法无关,只与SocketTimedoutException有关。

    来自 tcpdump 捕获的消息跟踪,如下所示:

    NO.            Time       Source Destination Protocol Info
    14845 2012-02-07 22:37:46 10.*   10.*        DNP 3. len=1,from 52156 to 29466,ACK 
    14846 2012-02-07 22:37:46 21.*   10.*        DNP 3. len=1,from 54562 to 50276,ACK
    14848 2012-02-07 22:37:46 32.*   10.*        DNP 3. [TCP Restransmission] len=1,from from 52156 to 29466,ACK 
    ……(7 times retransmission) 
    14849 2012-02-07 22:37:47 10.*   10.*        DNP 3. [TCP Restransmission] len=1,from from 52156 to 29466,ACK
    

    虽然此日志抛出 java.net.SocketException: Connection timed out at 22:54,大约 15 分钟后调用 writeObject。

    所以我们可以断定这个异常可能是由于长时间(大约30分钟)没有流量导致tcp连接不可用,同时没有调用socket.close()方法关闭socket实例,然后抛出此异常。

    所以为了避免这个异常,你应该使用方法 Socket.setKeepAlive() 方法保持连接处于活动状态,尽管你可能没有使用方法 setTimeout(),这意味着要求套接字无限阻塞接收;

    或者在您的应用程序中应用心跳机制。

    【讨论】:

    • 我收到套接字超时错误,每次都需要 16 分钟才能持续超时。我正在使用 jddc as400 并尝试设置 keep alive = true。我注意到你的超时时间是 15 分钟,所以我想知道你是否有更具体的内容,我可以试试 jdbc:as400://server.com:9471/table;secure=true;trace=true;keep alive=true;errors=full;extended dynamic=true;package=jbpkg;package cache=true;
    猜你喜欢
    • 2011-08-08
    • 1970-01-01
    • 2013-11-13
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多