1. Introduction
1.绪论
In this tutorial, we’ll focus on the timeout exceptions of Java socket programming. Our goal is to understand why these exceptions occur, and how to handle them.
在本教程中,我们将重点讨论Java套接字编程的超时异常。我们的目标是了解这些异常发生的原因,以及如何处理它们。
2. Java Sockets and Timeouts
2.Java套接字和超时
A socket is one end-point of a logical link between two computer applications. In other words, it’s a logical interface that applications use to send and receive data over the network.
套接字是两个计算机应用程序之间逻辑链接的一个端点。换句话说,它是一个逻辑接口,应用程序使用它在网络上发送和接收数据。
In general, a socket is a combination of an IP address and a port number. Each socket is assigned a specific port number that’s used to identify the service.
一般来说,套接字是一个IP地址和一个端口号的组合。每个套接字都被分配了一个特定的端口号,用来识别该服务。
Connection-based services use TCP-based stream sockets. For this reason, Java provides the java.net.Socket class for client-side programming. Conversely, server-side TCP/IP programming makes use of the java.net.ServerSocket class.
基于连接的服务使用基于TCP-的流插座。出于这个原因,Java为客户端编程提供了java.net.Socket类。反之,服务器端的TCP/IP编程则使用java.net.ServerSocket类。
Another type of socket is the UDP-based datagram socket, which is used for connectionless services. Java provides java.net.DatagramSocket for UDP operations. However, in this tutorial, we’ll focus on TCP/IP sockets.
另一种类型的套接字是基于UDP-的数据报套接字,它被用于无连接服务。Java为UDP操作提供了java.net.DatagramSocket。然而,在本教程中,我们将专注于TCP/IP套接字。
3. Connection Timed Out
3.连接超时
3.1. What Is “Connection Timed Out”?
3.1.什么是 “连接超时”?
For establishing a connection to the server from the client-side, the socket constructor is invoked, which instantiates a socket object. The constructor takes the remote host address and the port number as input arguments. After that, it attempts to establish a connection to the remote host based on the given parameters.
为了从客户端建立与服务器的连接,需要调用socket构造函数,它将实例化一个socket对象。构造函数将远程主机地址和端口号作为输入参数。之后,它试图根据给定的参数建立与远程主机的连接。
The operation blocks all other processes until a successful connection is made. However, if the connection isn’t successful after a certain time, the program throws a ConnectionException with a “Connection timed out” message:
该操作会阻止所有其他进程,直到成功连接为止。然而,如果连接在一定时间后没有成功,程序会抛出一个ConnectionException,并给出 “Connection timed out “消息。
java.net.ConnectException: Connection timed out: connect
From the server-side, the ServerSocket class continuously listens to incoming connection requests. When ServerSocket receives a connection request, it invokes the accept() method to instantiate a new socket object. Similarly, this method also blocks until it establishes a successful connection with the remote client.
在服务器端,ServerSocket类持续监听进入的连接请求。当ServerSocket收到一个连接请求时,它调用accept()方法来实例化一个新的socket对象。同样地,这个方法也会阻塞,直到它与远程客户端建立起成功的连接。
If the TCP handshakes aren’t complete, the connection remains unsuccessful. As a result, the program throws an IOException indicating that an error occurred while establishing a new connection.
如果TCP握手没有完成,连接仍然是不成功的。因此,程序会抛出一个IOException,表明在建立新连接时发生了错误。
3.2. Why It Occurs?
3.2.为什么会出现这种情况?
There can be several reasons for a connection timeout error:
连接超时错误可能有几个原因。
- No service is listening to the given port on the remote host
- The remote host isn’t accepting any connection
- The remote host isn’t available
- Slow internet connection
- No forwarding path to the remote host
3.3. How to Handle It?
3.3.如何处理?
Blocking times aren’t bounded, and a programmer can pre-set the timeout option for both client and server operations. For the client-side, we’ll first create an empty socket. After that, we’ll use the connect(SocketAddress endpoint, int timeout) method and set the timeout parameter:
阻塞时间不受限制,而且程序员可以为客户端和服务器操作预先设置超时选项。对于客户端,我们将首先创建一个空的套接字。之后,我们将使用connect(SocketAddress endpoint, int timeout)方法并设置超时参数。
Socket socket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(host, port);
socket.connect(socketAddress, 30000);
The timeout unit is in milliseconds and should be greater than 0. However, if the timeout expires before the method call returns, it will throw a SocketTimeoutException:
超时单位是毫秒,应该大于0。 但是,如果超时在方法调用返回之前就过期了,它将抛出一个SocketTimeoutException。
Exception in thread "main" java.net.SocketTimeoutException: Connect timed out
For the server-side, we’ll use the setSoTimeout(int timeout) method to set a timeout value. The timeout value defines how long the ServerSocket.accept() method will block:
对于服务器端,我们将使用setSoTimeout(int timeout)方法来设置一个超时值。timeout值定义了ServerSocket.accept()方法将阻塞多长时间。
ServerSocket serverSocket = new new ServerSocket(port);
serverSocket.setSoTimeout(40000);
Similarly, the timeout unit should be in milliseconds and should be greater than 0. If the timeout elapses before the method returns, it will throw a SocketTimeoutException.
同样地,timeout单位应该是毫秒,并且应该大于0。如果在方法返回前超时,它将抛出一个SocketTimeoutException。
Sometimes, firewalls block certain ports due to security reasons. As a result, a “connection timed out” error can occur when a client is trying to establish a connection to a server. Therefore, we should check the firewall settings to see if it’s blocking a port before binding it to a service.
有时,防火墙由于安全原因阻止了某些端口。因此,当客户端试图与服务器建立连接时,会出现 “连接超时 “的错误。因此,我们应该检查防火墙设置,看看它是否在绑定服务之前阻止了某个端口。
4. Read Timed Out
4.读取时间已到
4.1. What Is “Read Timed Out”?
4.1.什么是 “读取超时”?
The read() method call in the InputStream blocks until it finishes reading data bytes from the socket. The operation waits until it reads at least one data byte from the socket. However, if the method doesn’t return anything after an unspecified time, it throws an InterrupedIOException with a “Read timed out” error message:
InputStream中的read()方法调用会阻塞,直到它完成从套接字中读取数据字节的操作。然而,如果该方法在未指定的时间后没有返回任何东西,它会抛出一个InterrupedIOException,并给出 “Read timed out “错误信息。
java.net.SocketTimeoutException: Read timed out
4.2. Why It Occurs?
4.2.为什么会出现这种情况?
From the client side, the “read timed out” error happens if the server is taking longer to respond and send information. This could be due to a slow internet connection, or the host could be offline.
从客户端来看,”读取超时 “错误发生在如果服务器需要更长的时间来响应和发送信息。这可能是由于互联网连接缓慢,或者主机离线。
From the server side, it happens when the server takes a long time to read data compared to the preset timeout.
从服务器端来看,当服务器读取数据的时间比预设的超时时间长时就会发生这种情况。
4.3. How to Handle It?
4.3.如何处理?
For both the TCP client and server, we can specify the amount of time the socketInputStream.read() method blocks with the setSoTimeout(int timeout) method:
对于TCP客户端和服务器,我们可以指定socketInputStream.read()方法的时间用setSoTimeout(int timeout)方法阻塞。
Socket socket = new Socket(host, port);
socket.setSoTimeout(30000);
However, if the timeout elapses before the method returns, the program will throw a SocketTimeoutException.
然而,如果在方法返回之前超时,程序将抛出一个SocketTimeoutException。
5. Conclusion
5.总结
In this article, we discussed the timeout exceptions in Java socket programming, and learned how to handle them.
在这篇文章中,我们讨论了Java套接字编程中的超时异常,并学习了如何处理它们。
As always, the code is available over on GitHub.
像往常一样,代码可在GitHub上获得。