`
cuisuqiang
  • 浏览: 3962589 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
3feb66c0-2fb6-35ff-968a-5f5ec10ada43
Java研发技术指南
浏览量:3671990
社区版块
存档分类
最新评论

Socket 关于设置Socket连接超时时间

阅读更多

做网络编程的人对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

 

9
0
分享到:
评论
7 楼 bobogift 2017-08-10  
这个字段用法是如果相互之类超过多少时间没有数据交互,才抛出的
正确的使用姿势是你catch到异常 然后自己关闭
6 楼 fjjiaboming 2015-08-21  
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();
		}
	}
}

你这哪里有关闭?
5 楼 crazysummer 2014-01-23  
博主,想问下,如果我的客户端用Socket短连接传输较大的数据,并且要从服务器端获得返回信息,那个这个超时的时间是不是要设置得比我这个数据的传输时间更大呢?
4 楼 xiaoZ5919 2012-11-15  
socket的读写是阻塞的,soTimeout是socket读写超时,而不是链接超时。
connection reset是由于在一个半关闭的connection上读取数据导致,client已经关闭但是server端没有关闭。http://xiaoz5919.iteye.com/blog/1685138
3 楼 cuisuqiang 2012-11-14  
huzhenyu 写道
直接拔网线需要使用心脏机制,A给B一个验证消息若A能正常收到回执消息,则证明A网络正常。

心跳包我尝试了,没用,网线掉后还能正常发送!但是一段时间后才会心跳异常!
2 楼 huzhenyu 2012-11-14  
直接拔网线需要使用心脏机制,A给B一个验证消息若A能正常收到回执消息,则证明A网络正常。
1 楼 cuisuqiang 2012-11-14  
还有一个问题,那就是如果是程序或网卡主动断连接,那能捕获连接中断的异常,但是如果是把网线的话就获得不了!
不知道这种情况下如何判定网络的中断!有知道的请发表一下!

相关推荐

    c#socket连接池和连接超时时间设置

    提供一个c# socket连接池设计的例子,解决socket并发连接限制的问题,并且提供一种设置连接超时时间的方法,默认连接超时时间是不能设置的,提供了socket网络发送数据的接口.可用于pos小票打印机通讯。

    socket连接超时例程.rar

    1. **设置连接超时**: 易语言提供了设置Socket连接超时的API,比如`设置网络连接超时`命令,可以指定一个时间值(单位通常为毫秒),如果在这个时间内未完成连接,将会返回错误。 2. **异常处理**: 在进行...

    Linux下Socket连接超时的一种实现方法

    在 Linux 环境下,设置套接字(Socket)连接超时是一件非常重要的事情。下面我们将详细介绍 Linux 下 Socket 连接超时的一种实现方法。 首先,需要创建套接字,并将其设置成非阻塞状态。这是因为在连接时,我们不...

    windows下设置socket的connect超时

    在Windows环境下进行网络编程时,有时需要对socket连接进行超时控制,特别是在客户端与服务器通信的过程中,如果连接请求长时间没有响应,程序可能会陷入无休止的等待状态,从而导致资源浪费甚至程序卡死。...

    易语言socket连接超时例程

    易语言socket连接超时例程源码,socket连接超时例程,子程序1,socket,htons,inet_addr,Connect,closesocket,WSAStartup,setsockopt,ioctlsocket,select

    Tcpclient连接服务器连接超时设置

    同时,对于服务器性能或网络状况不佳的情况,适当的超时时间设置也至关重要。如果超时时间设置得过短,可能会频繁触发异常;如果设置得过长,可能会延迟程序的响应。因此,根据具体应用场景调整超时时间是非常必要的...

    Java中Socket设置连接超时的代码分享

    Java中Socket设置连接超时的代码分享 Java 中 Socket 设置连接超时是非常重要的,因为如果超时时长过长的...Java 中 Socket 设置连接超时是非常重要的,它可以帮助我们避免由于长时间等待连接而影响测试和用户体验。

    socket非阻塞超时设置

    2. 使用`setsockopt()`函数设置连接超时和读/写超时。 3. 处理非阻塞模式下的`WSAEWOULDBLOCK`错误码。 4. 在非阻塞模式下,可能需要多次尝试读取或写入以确保所有数据都被正确处理。 在实际开发中,理解并正确运用...

    Java实现Socket长连接和短连接

    - **关闭策略**:合理设置超时时间,当连接长时间无数据传输时,可以考虑关闭连接以释放资源。 **4. 应用场景** 短连接适合一次性、低延迟、资源有限的场景,如网页浏览。而长连接适合实时性强、需要持续交互的...

    易语言源码易语言socket连接超时源码例程.rar

    在网络通信中,由于各种原因(如网络延迟、服务器繁忙等),socket连接可能会出现长时间无法完成的情况,这时就需要设置连接超时机制。超时机制可以避免程序因为等待连接响应而无限期阻塞,提高程序的健壮性和用户...

    易语言socket连接超时源码例程.rar

    源代码通常包括了创建Socket对象、设置连接超时参数、发起连接尝试以及处理超时异常等关键步骤。开发者可以通过阅读和分析这段代码,学习如何在易语言中处理网络连接的超时问题。 "源码使用说明.txt"文件则为用户...

    java socket连接池 实现

    1. 初始化连接池:设置最大连接数、最小连接数、超时时间等参数,并预创建一部分Socket连接。 2. 获取连接:当应用程序需要建立Socket连接时,从连接池中获取一个闲置的Socket,如果没有,则等待直到有连接被归还或...

    异步发送解决socket连接超时

    利用新建类,异步传送参数,解决断连接向多个ip发送socket包产生socket.connect超时的问题。实现向每一个ip发送包新建立一个线程,由于是新建立的线程,全部异步,所以没法记录文本文件(同一个文件同时被记录),...

    c# socket设置代理

    对于HTTP代理,可能需要在连接前构造一个`HttpWebRequest`对象,设置其代理属性,然后通过`HttpWebRequest.GetResponse()`获取到连接,再从连接中获取Socket。 5. **建立连接**:使用`Socket.Connect()`方法连接到...

    python设定并获取socket超时时间的方法

    接着,通过调用`settimeout(100)`方法将其超时时间设置为100秒,并再次打印确认。 #### 三、Socket超时的获取方法 可以通过`gettimeout()`方法来获取当前Socket对象的超时时间。如果之前未设置超时时间,则返回...

    Socket接受数据超时

    在Java中,我们可以使用Socket对象的setSoTimeout()方法来设置一个特定的等待时间。如果在这个时间内没有接收到数据,将会抛出SocketTimeoutException异常,从而中断阻塞状态。 然而,传统的Socket编程模型通常使用...

    socket服务器接收数据

    socket 接收多个终端上传的数据 ,每个终端新建一个socket,超时的socket定时清理,防止连接过多影响服务器性能

    socket客户端,可连接多个服务器

    3. 重试策略:设置合理的重试次数和间隔时间,防止频繁重连对服务器造成压力。 4. 断线通知:在重连过程中,客户端可能需要通知用户当前的连接状态,以便用户了解情况。 在压缩包中的`iSocket`文件可能是实现这个...

    socket 客户端连接池实现

    在实际应用中,合理设置连接池的参数至关重要,包括最小连接数、最大连接数、超时时间等。这些参数需要根据系统的并发量、网络环境以及服务器处理能力进行调整,以达到最佳性能。 总结来说,Socket客户端连接池是...

    socket线程连接池实例

    通常,我们会在工厂类中设置Socket的连接参数,如超时时间、套接字选项等。 2. **配置GenericObjectPool**:接着,我们需要对`GenericObjectPool`进行配置,包括设置最大池大小、空闲超时时间、是否允许空闲对象...

Global site tag (gtag.js) - Google Analytics