Java network server and TIME_WAIT

2019-02-20 00:41发布

I have run into a problem with a network server that receives signals from devices my company produces. The device will occasionally reuse the source port that it had just used. This causes the SYN to be dropped by the server. The device then retries until the old socket falls out of TIME_WAIT on the server. The server then SYN-ACKs.

The server is written in Java. Unfortunately, modifying the device to cycle ports correctly is not an option, as there are many in the field, and updating the existing units is not an option. The old software was written in C++ and somehow expunged the TIME_WAIT port from the list in the Windows TCP stack.

Can anyone offer me any advice on how to circumvent TIME_WAIT from Java on Windows?

EDIT: I have indeed confirmed in Wireshark that the device is reusing a recently used port.

On the server socket I am using the following options:

socket = new ServerSocket();
socket.setPerformancePreferences(3, 2, 1);
socket.setReuseAddress(true);
socket.setSoTimeout(CLIENT_READ_TIMEOUT);
socket.bind(new InetSocketAddress(group.getPort()), MAX_TCP_BACKLOG);

And the client socket has the following set after receiving:

Socket client = server.accept();
client.setKeepAlive(false);
client.setSoLinger(true, 0);
client.setReuseAddress(true);
client.setTcpNoDelay(true);
client.setSoTimeout(CLIENT_READ_TIMEOUT);

I have tried SO_LINGER as both true and false, with the exact same trace results. CLIENT_READ_TIMEOUT is set to 10 seconds.

3条回答
男人必须洒脱
2楼-- · 2019-02-20 01:07

The old not-recommended trick to avoid TIME_WAIT is to set SO_LINGER socket option to { 1, 0 } - the close then sends RST instead of doing normal flush/four-way exchange sequence, thus avoiding the TIME_WAIT all together (be warned - you might lose tail of what you still have in the send buffer.) I can't comment on whether this could be done in Java though.

EDIT: Can you confirm with tcpdump that the clients really reuse source port numbers? If not, this might just be the classic case for SO_REUSEADDR listening socket option as Jon pointed out.

查看更多
SAY GOODBYE
3楼-- · 2019-02-20 01:22

The server is ignoring the SYN packets from the client because it cannot distinguish between those for a new session using the old source port and retransmissions from the old session. If you circumvent the TIME_WAIT state on the server, by setting the system timer interval for aging out TIME_WAIT state entries in the control block table, then how will your server properly ignore SYN retransmissions for sessions that have already terminated?

查看更多
Summer. ? 凉城
4楼-- · 2019-02-20 01:29

Building on Nikolai's answer,

Socket s;
...
s.setSoLinger(true,0);

would be the equivalent in Java.

EDIT: Another thing you might like to look at would be setReuseAddress(true);

查看更多
登录 后发表回答