做网络编程的人对setSoTimeout方法一定很熟悉,都知道是设置连接的超时时间!
但是我在网上找资料时发现很多人把这个超时时间理解成了链路的超时时间!我看了一下JDK 关于这个方法的说明,其实根本不是链路的超时时间!
setSoTimeout public void setSoTimeout(int timeout) throws SocketException启用/禁用带有指定超时值的 SO_TIMEOUT,以毫秒为单位。将此选项设为非零的超时值时,在与此 Socket 关联的 InputStream 上调用 read() 将只阻塞此时间长度。 如果超过超时值,将引发 java.net.SocketTimeoutException,虽然 Socket 仍旧有效。选项必须在进入阻塞操作前被启用才能生效。 超时值必须是 > 0 的数。超时值为 0 被解释为无穷大超时值。 参数: timeout - 指定的以毫秒为单位的超时值。 抛出: SocketException - 如果底层协议出现错误,例如 TCP 错误。 从以下版本开始: JDK 1.1 另请参见: getSoTimeout()
其实说白了他只是read方法的超时时间,这个方法是堵塞的!
写个小例子验证一下:
服务端,收到一个请求后处理,但是只处理一个请求,处理完毕后结束:
package socket; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; import java.net.SocketTimeoutException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; public class SocketService { public static void main(String[] args) { try { SocketAddress address = new InetSocketAddress("192.168.9.155", 30001); // 启动监听端口 8001 ServerSocket ss = new ServerSocket(); ss.bind(address); // 接收请求 Socket s = ss.accept(); new Thread(new T(s)).start(); } catch (Exception e) { e.printStackTrace(); } } } class T implements Runnable { public void run() { try { System.out.println(socket.toString()); socket.setKeepAlive(true); socket.setSoTimeout(5 * 1000); String _pattern = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat format = new SimpleDateFormat(_pattern); while (true) { System.out.println("开始:" + format.format(new Date())); try { InputStream ips = socket.getInputStream(); ByteArrayOutputStream bops = new ByteArrayOutputStream(); int data = -1; while((data = ips.read()) != -1){ System.out.println(data); bops.write(data); } System.out.println(Arrays.toString(bops.toByteArray())); }catch(SocketTimeoutException e){ e.printStackTrace(); }catch(SocketException e){ e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } Thread.sleep(1000); System.out.println(socket.isBound()); // 是否邦定 System.out.println(socket.isClosed()); // 是否关闭 System.out.println(socket.isConnected()); // 是否连接 System.out.println(socket.isInputShutdown()); // 是否关闭输入流 System.out.println(socket.isOutputShutdown()); // 是否关闭输出流 System.out.println("结束:" + format.format(new Date())); } } catch (Exception e) { e.printStackTrace(); } } private Socket socket = null; public T(Socket socket) { this.socket = socket; } public Socket getSocket() { return socket; } public void setSocket(Socket socket) { this.socket = socket; } }
第一个客户端,连接后一直保持连接对象的存活,但是不发送数据,服务端打印:
package socket; import java.net.Socket; public class Client { public static void main(String[] args) { try { Socket socket = new Socket("192.168.9.155", 30001); socket.setKeepAlive(true); while(true && null != socket){ Thread.sleep(10 * 1000); } } catch (Exception e) { e.printStackTrace(); } } }
打印如下,可以看到链路一直是活的,间隔超时时间的间隔就打印一组异常信息:
Socket[addr=/192.168.9.155,port=3017,localport=30001] 开始:2012-11-14 11:15:30 java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(Unknown Source) at java.net.SocketInputStream.read(Unknown Source) at socket.T.run(SocketService.java:42) at java.lang.Thread.run(Unknown Source) true false true false false 结束:2012-11-14 11:15:36 开始:2012-11-14 11:15:36 java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(Unknown Source) at java.net.SocketInputStream.read(Unknown Source) at socket.T.run(SocketService.java:42) at java.lang.Thread.run(Unknown Source) true false true false false 结束:2012-11-14 11:15:42 开始:2012-11-14 11:15:42
然后我们编写一个客户端,连接后马上关闭连接,也不发送任何数据:
package socket; import java.net.Socket; public class Client { public static void main(String[] args) { try { Socket socket = new Socket("192.168.9.155", 30001); socket.setKeepAlive(true); } catch (Exception e) { e.printStackTrace(); } } }
打印如下:
开始:2012-11-14 11:17:42 java.net.SocketException: Connection reset at java.net.SocketInputStream.read(Unknown Source) at java.net.SocketInputStream.read(Unknown Source) at socket.T.run(SocketService.java:42) at java.lang.Thread.run(Unknown Source) true false true false false java.net.SocketException: Connection reset at java.net.SocketInputStream.read(Unknown Source) at java.net.SocketInputStream.read(Unknown Source) at socket.T.run(SocketService.java:42) at java.lang.Thread.run(Unknown Source) 结束:2012-11-14 11:17:43 开始:2012-11-14 11:17:43 true false true false false 结束:2012-11-14 11:17:44
异常是不一样的,不一样的还有,如果是超时,则五秒钟循环一次,然后是连接中断,则不在循环马上再报错,因为连接已经挂了!但是打印这个连接还是有效的,这个我也不知道怎么回事!
所以,如果大家理解为超时时间内没有数据连接就自动关闭或失效,那么这个理解就非常有问题了!
请您到ITEYE看我的原创:http://cuisuqiang.iteye.com
或支持我的个人博客,地址:http://www.javacui.com
相关推荐
提供一个c# socket连接池设计的例子,解决socket并发连接限制的问题,并且提供一种设置连接超时时间的方法,默认连接超时时间是不能设置的,提供了socket网络发送数据的接口.可用于pos小票打印机通讯。
本文详细介绍了目前各平台通用的设置套接字(Socket)连接超时的办法,介绍了Linux环境下的Socket连接超时的一种实现方法。
易语言socket连接超时例程源码,socket连接超时例程,子程序1,socket,htons,inet_addr,Connect,closesocket,WSAStartup,setsockopt,ioctlsocket,select
socket连接超时例程.rar
在我们日常连接中,如果超时时长过长的话,在开发时会影响测试,下面这篇文章主要给大家分享了关于Java中Socket设置连接超时的代码,需要的朋友可以参考借鉴,下面来一起看看吧。
变相的实现connect的超时,我要讲的就是这个方法,原理上是这样的: 1.建立socket 2.将该socket设置为非阻塞模式 3.调用connect() 4.使用select()检查该socket描述符是否可写(注意,是可写) 5.根据select()...
socket非阻塞超时设置可编译。VC6
socket 接收多个终端上传的数据 ,每个终端新建一个socket,超时的socket定时清理,防止连接过多影响服务器性能
利用新建类,异步传送参数,解决断连接向多个ip发送socket包产生socket.connect超时的问题。实现向每一个ip发送包新建立一个线程,由于是新建立的线程,全部异步,所以没法记录文本文件(同一个文件同时被记录),...
易语言socket连接超时源码例程.zip易语言项目例子源码下载易语言socket连接超时源码例程.zip易语言项目例子源码下载 1.合个人学习技术做项目参考 2.适合学生做毕业设计参考 3.适合小团队开发项目参考
易语言源码易语言socket连接超时源码例程.rar
.Net Socket库的SocketOptionName.SendTimeout提供了控制发送数据的超时时间,但并非本文讨论的连接请求的超时时间。实现下面是实现的关键代码: 代码如下:class TimeOutSocket{ private static bool I
librtmp长时间直播socket连接断开的原因 librtmp长时间直播socket连接断开的原因 librtmp长时间直播socket连接断开的原因 librtmp长时间直播socket连接断开的原因
易语言socket连接超时源码例程.rar
python写法 import socket def test_socket_timeout(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print "Default socket timeout: %s" %s.get... #针对单个socket实例的超时 test_socket_timeout
Socket接受数据超时,采用Callable 接口实现
在linux上通过JDBC连接ORACLE 时总是出现 java.sql.SQLRecoverableException: IO Error: Connection reset 的问题
方法有连接socket的超时参数,但是没有类似C中的连接成功后对数据的读写超时参数设置。没关系,PHP中对stream提供了一系列的方法以防止超时 stream_set_blocking( $fp , false ) 设置数据流为阻塞模式,以防止数据...
本文实例讲述了C++设置超时时间的简单实现方法,代码简单易懂,功能实用。分享给大家供大家参考。具体实现方法如下: 代码如下:BOOL SetTimeOut(SOCKET s, int nTime, BOOL bRecv) { int ret = ::setsockopt...