';ServerSocket.accept()';不带SocketTimeoutException的循环(Java)(替代解决方案)
解释 我正在重温我曾经自学Java的项目 在这个项目中,我希望能够阻止服务器接受新客户机,然后在退出JVM之前执行一些“清理”操作 在该项目中,我对客户机接受/处理循环使用了以下样式:';ServerSocket.accept()';不带SocketTimeoutException的循环(Java)(替代解决方案),java,multithreading,sockets,exception,Java,Multithreading,Sockets,Exception,解释 我正在重温我曾经自学Java的项目 在这个项目中,我希望能够阻止服务器接受新客户机,然后在退出JVM之前执行一些“清理”操作 在该项目中,我对客户机接受/处理循环使用了以下样式: //Exit loop by changing running to false and waiting up to 2 seconds ServerSocket serverSocket = new ServerSocket(123); serverSocket.setSoTimeout(2000); Soc
//Exit loop by changing running to false and waiting up to 2 seconds
ServerSocket serverSocket = new ServerSocket(123);
serverSocket.setSoTimeout(2000);
Socket client;
while (running){ // 'running' is a private static boolean
try{
client = serverSocket.accept();
createComms(client); //Handles Connection in New Thread
} catch (IOException ex){
//Do Nothing
}
}
在这种方法中,如果没有客户端连接,则每2秒就会抛出一次SocketTimeoutException,我不喜欢依赖异常进行正常操作,除非有必要 我一直在尝试以下风格,以尽量减少对正常操作异常的依赖:
//Exit loop by calling serverSocket.close()
ServerSocket serverSocket = new ServerSocket(123);
Socket client;
try{
while ((client = serverSocket.accept()) != null){
createComms(client); //Handles Connection in New Thread
}
} catch (IOException ex){
//Do Nothing
}
在本例中,我的意图是只有在调用serverSocket.close()或出现问题时才会抛出异常
问题
这两种方法是否存在显著差异,或者它们都是可行的解决方案
我完全是自学成才的,所以我不知道我是不是无缘无故地发明了轮子,还是想出了什么好主意
我已经潜伏了一段时间,这是我第一次没有找到我需要的东西
请随意建议完全不同的方法=3非阻塞IO是您需要的。如果当前没有要接受的连接,它将返回
null
,而不是阻塞直到返回SocketChannel
(非阻塞替代Socket
)
这将允许您删除超时,因为不会有任何阻塞
您还可以注册一个选择器
,它会在有连接要接受或有数据要读取时通知您。我有一个小例子,以及一个不使用选择器的非阻塞ServerSocket
编辑:如果我的链接出现问题,下面是无选择器的非阻塞IO示例,接受连接:
class Server {
public static void main(String[] args) throws Exception {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
while(true) {
SocketChannel sc = ssc.accept();
if(sc != null) {
//handle channel
}
}
}
}
第二种方法的问题是,如果while循环中发生异常,服务器将死亡 第一种方法更好,尽管您可能希望使用Log4j添加日志异常
while (running){
try{
client = serverSocket.accept();
createComms(client);
} catch (IOException ex){
// Log errors
LOG.warn(ex,ex);
}
}
第二种方法更好(因为您提到的原因:在正常程序流中依赖异常不是一种好的做法),尽管您的代码建议
serverSocket.accept()
可以返回null
,但它不能返回。不过,该方法可以抛出各种异常(请参见)。您可能希望捕获这些异常:没有很好的理由,服务器不应该停机
我已经成功地使用了第二种方法,但添加了更多的代码以使其更稳定/可靠:请参阅我对它的看法(单元测试)。要考虑的“清理”任务之一是给处理客户端通信的线程提供一些时间,以便这些线程能够完成或正确地通知客户端连接将被关闭。这可以防止客户端在连接突然丢失/关闭之前无法确定服务器是否完成了一项重要任务的情况。“我不喜欢依赖异常进行正常操作,除非有必要”OMG另一个异常。这是必要的。
setSoTimeout()
机制正是为此目的而提供的,而SocketTimeoutException
是其接口的一部分。不要让任意的编程美学妨碍实现正确的代码。强制执行IOException:socketclosed
比捕获SocketTimeoutException
更好吗?我不确定在这种情况下是否有必要,这就是为什么我要问的原因。我最初的想法是,抛出一个异常比每2秒抛出一个异常要好。第二种方法是相同的,因为他提到的原因。它只是将IOException
交换为SocketTimeoutException
。感谢您的建议!是时候修补新玩具了=3张桌子,你的回答告诉我要避免使用SOTimeout,只需关闭插座即可强制关闭异常,这是一种更干净、更简单的方法:)