ServerSocket卡在accept的时候怎么正确关闭
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ServerSocket卡在accept的时候怎么正确关闭相关的知识,希望对你有一定的参考价值。
加入一个ServerSocket正在另一个线程堵塞accept,那如何停止accept或者关闭Socket?Server socket 设置下超时
setSoTimeout
然后在Listen线程中用interrupt
其实直接close socket也可以,不过会抛出异常,我的意思是有什么比较安全而又简单的办法?难道要加一个标志,然后要关闭的时候把标志设为stop,然后连接listernSocket?这样也未免太麻烦了
JDK5.0里面新增了Java.util.concurrent包(对于多线程的开发建议尽量使用这个包),下面是javadoc里面的样例代码
用法示例
下面给出了一个网络服务的简单结构,这里线程池中的线程作为传入的请求。它使用了预先配置的 Executors.newFixedThreadPool(int) 工厂方法:
java 代码
class NetworkService implements Runnable
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port, int poolSize)
throws IOException
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
public void run() // run the service
try
for (;;)
pool.execute(new Handler(serverSocket.accept()));
catch (IOException ex)
pool.shutdown();
class Handler implements Runnable
private final Socket socket;
Handler(Socket socket) this.socket = socket;
public void run()
// read and service request on socket
下列方法分两个阶段关闭 ExecutorService。第一阶段调用 shutdown 拒绝传入任务,然后调用 shutdownNow(如有必要)取消所有遗留的任务:
java 代码
void shutdownAndAwaitTermination(ExecutorService pool)
pool.shutdown(); // Disable new tasks from being submitted
try
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
catch (InterruptedException ie)
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
内存一致性效果:线程中向 ExecutorService 提交 Runnable 或 Callable 任务之前的操作 happen-before 由该任务所提取的所有操作,后者依次 happen-before 通过 Future.get() 获取的结果。 参考技术A serverSocket会一直接受连接,直到running设为false。
但问题是如果我程序要退出了,就算把running设为false,accept也会卡在那里,所以必须再接受一次连接程序才能退出。
如果我退出时直接关闭ServerSocket比如serverSocket.close(),那么程序是可以马上结束,但是accept会抛异常,结果就是每次结束程序都有异常。
ServerSocket类的常用方法
1.accept:侦听并接受此套接字的连接;此方法在连接传入之前一直阻塞。
2.setSoTimeout(timeout)方法的作用时设置超时时间,通过指定超时timeout值启用/禁用超时功能,以ms为单位。
必须在进入阻塞前调用这个方法,才能生效,一旦超时,程序会触发SocketTimeoutException异常;默认值是0即永远等待。
Server.java
package com.company.s7; import java.io.IOException; import java.net.ServerSocket; public class Server public static void main(String[] args) try ServerSocket serverSocket=new ServerSocket(8000); System.out.println(serverSocket.getSoTimeout()); serverSocket.setSoTimeout(4000); System.out.println(serverSocket.getSoTimeout()); System.out.println(); System.out.println("begin "+System.currentTimeMillis()); serverSocket.accept(); System.out.println(" end "+System.currentTimeMillis()); catch (IOException e) e.printStackTrace();
Client.java
package com.company.s7; import java.io.IOException; import java.net.Socket; public class Client public static void main(String[] args) try System.out.println("client begin "+System.currentTimeMillis()); Socket socket=new Socket("localhost",8000); System.out.println("client end "+System.currentTimeMillis()); catch (IOException e) e.printStackTrace(); System.out.println("catch "+System.currentTimeMillis());
backlog参数含义:
允许接受客户端连接请求的个数。
如果队列已满,则拒接该连接。
blacklog参数如果小于等于0,则使用默认值50;
以上是关于ServerSocket卡在accept的时候怎么正确关闭的主要内容,如果未能解决你的问题,请参考以下文章
Java - 如何检查 ServerSocket.accept() 是不是连接?
如何中断 ServerSocket accept() 方法?
ServerSocket对象调用accept()方法返回一个啥类型的对象?
网络I/O模型--03非阻塞模式(ServerSocket与Socket的超时处理)--解除accept() read()方法阻塞