Socket

1 Java Impl

Socket socket = new Socket();
socket.setReuseAddress(true);
socket.setKeepAlive(true); // Will monitor the TCP connection is
// valid
socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to
// ensure timely delivery of data
socket.setSoLinger(true, 0); // Control calls close () method,

1.1 setReuseAddress

SO_REUSEADDR allows your server to bind to an address which is in a TIME_WAIT state. It does not allow more than one server to bind to the same address. It was mentioned that use of this flag can create a security risk because another server can bind to a the same port, by binding to a specific address as opposed to INADDR_ANY.

This socket option tells the kernel that even if this port is busy (in the TIME_WAIT state), go ahead and reuse it anyway. If it is busy, but with another state, you will still get an address already in use error. It is useful if your server has been shut down, and then restarted right away while sockets are still active on its port.

TCP's primary design goal is to allow reliable data communication in the face of packet loss, packet reordering, and — key, here — packet duplication.

It's fairly obvious how a TCP/IP network stack deals with all this while the connection is up, but there's an edge case that happens just after the connection closes. What happens if a packet sent right at the end of the conversation is duplicated and delayed, such that the 4-way shutdown packets get to the receiver before the delayed packet? The stack dutifully closes down its connection. Then later, the delayed duplicate packet shows up. What should the stack do?

More importantly, what should it do if the program that owned that connection immediately dies, then another starts up wanting the same IP address and TCP port number?

There are a couple of choices:

1.1.1 选择一

Disallow reuse of that IP/port combo for at least 2 times the maximum time a packet could be in flight. In TCP, this is usually called the 2×MSL delay. You sometimes also see 2×RTT, which is roughly equivalent.

This is the default behavior of all common TCP/IP stacks. 2×MSL is typically between 30 and 120 seconds. (This is the TIME_WAIT period.) After that time, the stack assumes that any rogue packets have been dropped en route due to expired TTLs, so it leaves the TIME_WAIT state, allowing that IP/port combo to be reused.

1.1.1 选择二

Allow the new program to re-bind to that IP/port combo. In stacks with BSD sockets interfaces — essentially all Unixes and Unix-like systems, plus Windows via Winsock — you have to ask for this behavior by setting the SO_REUSEADDR option via setsockopt() before you call bind().

SO_REUSEADDR is most commonly set in server programs.

The reason is, a common pattern is that you change a server configuration file and need to restart that server to make it reload its configuration. Without SO_REUSEADDR, the bind() call in the restarted program's new instance will fail if there were connections open to the previous instance when you killed it. Those connections will hold the TCP port in the TIME_WAIT state for 30-120 seconds, so you fall into case 1 above.

The safe thing to do is wait out the TIME_WAIT period, but in practice this isn't a big enough risk that it's worth doing that. It's better to get the server back up immediately so as to not miss any more incoming connections than necessary.

What is the difference between SO_REUSEADDR and SO_REUSEPORT?

What is the meaning of SO_REUSEADDR (setsockopt option)

1.2 Tcp state diagram

1.3 setSoLinger

Java Socket中,当我们调用Socketclose方法时,默认的行为是当底层网卡所有数据都发送完毕后,关闭连接

通过setSoLinger方法,我们可以修改close方法的行为

  1. setSoLinger(true, 0)

当网卡收到关闭连接请求后,无论数据是否发送完毕,立即发送 RST 包关闭连接

  1. setSoLinger(true, delay_time)

当网卡收到关闭连接请求后,等待 delay_time

如果在 delay_time 过程中数据发送完毕,正常四次挥手关闭连接

如果在 delay_time 过程中数据没有发送完毕,发送 RST 包关闭连接

细说Java Socket中的setSoLinger方法

1.4 setTcpNoDelay - 内格尔算法

First of all not both of them disables Nagle's algorithm.

Nagle's algorithm is for reducing more number of small network packets in wire. The algorithm is: if data is smaller than a limit (usually MSS), wait until receiving ACK for previously sent packets and in the mean time accumulate data from user. Then send the accumulated data.

if [ data > MSS ]
    send(data)
else
    wait until ACK for previously sent data and accumulate data in send buffer (data)
    And after receiving the ACK send(data)

This will help in applications like telnet. However, waiting for the ACK may increase latency when sending streaming data. Additionally, if the receiver implements the 'delayed ACK policy', it will cause a temporary deadlock situation. In such cases, disabling Nagle's algorithm is a better option.

So TCP_NODELAY is used for disabling Nagle's algorithm.

TCP_CORK aggressively accumulates data. If TCP_CORK is enabled in a socket, it will not send data until the buffer fills to a fixed limit. Similar to Nagle's algorithm, it also accumulates data from user but until the buffer fills to a fixed limit not until receiving ACK. This will be useful while sending multiple blocks of data. But you have to be more careful while using TCP_CORK.

Until 2.6 kernel, both of these options are mutually exclusive. But in later kernel, both of them can exist together. In such case, TCP_CORK will be given more preference.

When should I use TCP_NODELAY and when TCP_CORK?

1.5 setKeepAlive

TODO

Does a TCP socket connection have a “keep alive”?

results matching ""

    No results matching ""