Вы находитесь на странице: 1из 3

TCP Socket Connection Close

Consider the scenario where clients connect to the server and the server keeps the sockets alive for push notifications or other commands. For example, the server can keep the sockets into some collection. It is very important that the server discards particular TCP socket as long as it detects the socket is not valid anymore. Consider the following Client/Server demonstration classes. Server.java
import import import import java.io.OutputStream; java.net.InetAddress; java.net.ServerSocket; java.net.Socket;

public class Server { public static void main(String[] args) throws Throwable { ServerSocket ss = new ServerSocket(2345,10, InetAddress.getByName("192.168.2.2")); Socket s = ss.accept(); OutputStream os = s.getOutputStream(); Thread.sleep(5000); for (int i = 0; i < 3; i++) { os.write("A".getBytes()); os.flush(); System.out.println("Written in cycle " + i); } os.close(); s.close(); } }

Client.java
import java.net.Socket; public class Client { public static void main(String[] args) throws Throwable { Socket s = new Socket("192.168.2.2", 2345); s.close(); } }

1. Start the server. 2. Start the client that connects to the server and closes immediately. 3. Wait for server completion and observe the server's output. The output produced is the following:

Written in cycle 0 Exception in thread "main" java.net.SocketException: Software caused connection abort: socket write error at java.net.SocketOutputStream.socketWrite0(Native Method) at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92) at java.net.SocketOutputStream.write(SocketOutputStream.java:124) at Server.main(Server.java:15)

Does something look strange in the above trace? The first write operation on the server was successful, but the client socket was closed 5 seconds before! The exception was thrown after the server's second write attempt. Here is the Wireshark trace output:

When the client closes the socket, a TCP packet with FIN flag is sent (packet 4). For the server, the FIN flag does not mean that the client is not accepting data. Rather, the FIN flag means that the client does not send data that point further. TCP communication consists of two separate streams in each direction that are controlled independently. In the above scenario, the server does not know that the client is not listening anymore for incoming data, so it sends PSH (push) packet with data (packet 6). This is the first cycle that was successful on the server. The client's operating systems responds with RST (reset) packet (packet 7). The server knows that the client is no more willing to accept data or it is not available at all only if RST packet is received. After that the server throws an exception after the second write attempt. The final consequence is that we don't detect the closed sockets immediately, i.e. the server keeps phantom sockets and performs one additional write operation per already closed socket. We can fix the client by setting the TCP LINGER option: Client.java
import java.net.Socket; public class Client { public static void main(String[] args) throws Throwable { Socket s = new Socket("192.168.2.2", 2345); s.setSoLinger(true, 0); s.close(); } }

The Wireshark trace output now is:

Notice that the RST packet was sent immediately when the client closed the socket. Here is a nice article that explains various options for TCP socket closing in Java programs: http://download.oracle.com/javase/1.5.0/docs/guide/net/articles/connection_relea se.html

Вам также может понравиться