出于学习目的,我正在编写Java TCP服务器。这被包装到它自己的类SyteTCPServer
中,它使用ServerSocket
来处理连接逻辑。这适用于学校项目,其中良好的代码实践非常重要。
它被放入自己的类的原因是因为有一个特定的应用程序级协议。该课程是大型项目的一部分。
当谷歌搜索时,我只发现人们将所有ServerSocket
及其附带的逻辑直接放在主方法中。我不确定在OOP方面该怎么做?
我的SyteTCPServer
有一个简单的Start()
和Stop()
方法,它隐藏了使用ServerSocket
,处理客户端等的实现。
但是,我有点难过,因为有很多网络功能,IntelliJ警告我要捕获IOExceptions。接受客户端可能会抛出IOException,因此可以获取所述客户端的输出流,因此可以writeBytes
,...您明白我的观点。
在抽象的背景下,我如何才能最好地解决这些异常?我是否在方法旁边写了throws IOException
,将较高代码try...catch
设为SyteTCPServer.Start
?
此外,如果整个服务器停止必须发生任何异常,或者我“隐藏”其中一个客户端未正确连接的事实?或者,当客户端连接失败时,我应该触发事件吗?我真的不知道..
由于UI /核心代码分离,我还避免在因瘟疫而发生异常时编写输出。
我希望这些问题不会太多。
这是我的start方法的示例,抛出IOException:
public void Start() throws IOException {
this.listenSocket = new ServerSocket(this.port);
Listen();
}
答案 0 :(得分:1)
我认为区分您可能收到的不同IOExceptions非常重要。例如,在连接已经建立的情况下创建新连接是一个例外,它是否是一个预期的错误?最简单的方法是阅读documentation并根据具体情况处理错误:
用于构建服务器套接字:
public ServerSocket(int port)抛出IOException
- IOException - 如果在打开套接字时发生I / O错误。
- SecurityException - 如果存在安全管理器且其checkListen方法不允许该操作。
- IllegalArgumentException - 如果port参数超出指定的有效端口值范围,介于0和65535之间(包括0和65535)。
接受连接:
public Socket accept()抛出IOException
- IOException - 如果在等待连接时发生I / O错误。
- SecurityException - 如果存在安全管理器且其checkAccept方法不允许该操作。
- SocketTimeoutException - 如果之前使用setSoTimeout设置了超时并且已达到超时。
- IllegalBlockingModeException - 如果此套接字具有关联的通道,则该通道处于非阻塞模式,并且没有可以接受的连接
等等。
关于在何处捕获异常:这还取决于您希望服务器在特定情况下执行的操作。但总的来说,捕捉“预期”错误并在那里处理它们,但将非故意错误提升到更高的水平。
我的意思是:
public void foo() throws IOException {
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
// Port is in use -> perhaps retry on another port
// If things fail, throw exception anyway
} finally {
if (!serverSocket.isClosed()) {
try {
serverSocket.close();
} catch (IOException e) {
// This exception is to be taken care of internally, not thrown
}
}
}
}
另请注意,这不仅适用于服务器端,也适用于客户端。
写好你的服务器祝你好运!
答案 1 :(得分:1)
我只发现人们把所有的ServerSocket及其随附 直接在main方法内部的逻辑。我不确定是不是这样 谈到OOP?
将所有ServerSocket
创建代码及其后续逻辑直接用main()
方法接受,处理和读/写到客户端绝对不是一个好的OOP实践。
使用OOP,我们应该从对象的角度思考这些对象如何相互交互以满足所需的功能。每个对象都包含一个独特的责任。
接受客户端可能会抛出IOException,因此可以获取 所述客户端的输出流,所以可以写上字符,...你明白我的意思。
在抽象的背景下,我如何才能最好地实现这些目标 异常?我是否在方法旁边写了一个抛出IOException 更高级的代码尝试...抓住SyteTCPServer.Start?
我可以强调的几个最佳实践
此外,如果整个服务器停止必须发生任何异常,或者我 “隐藏”其中一个客户端连接不正确的事实?要么 也许,当客户端连接失败时,我应该触发事件吗?
当你开始实现代码时,我相信你会发现更多的类,其中一个可以在一个单独的线程中处理每个客户端连接请求,比如ClientConnectionHandler
对象(Thread),这样其他客户端未被阻止。因此,每个客户端连接都将成为一个独立的执行线程。
使用此设计,如果异常特定于该客户端连接,则无需关闭整个服务器。只需终止该客户端线程并清理资源就足够了。