Use TCP_QUICKACK and SO_LINGER to eliminate the 3rd packet in tcp handshake

Find an insterest project, to remove last packet in 3-way tcp handshake, https://github.com/tevino/tcp-shaker

Disable TCP_QUICKACK(linux 2.4.4+) will prevent connect to sending ack(3 packet) immediatelly, this could make place for no 4 way termination(sync -> ack+sync -> rst). Haproxy use this strategy to do tcp health check

默认情况connect完成即三次握手结束,设置TCP_QUICKACK为0(默认1)的话,connect完了还会等一段时间才会发ack(个人理解)tcp-3way-handshak

The last ACK in the TCP handshake can already contain a payload. But, this is usually not done since the application first calls connect and then will either wait for the server to reply or send its first data. Since the kernel does not know what the application will do next it will already send out the ACK within the connect so that the server knows as fast as possible that the connection is established.
Depending on your OS it might be possible to change this behavior and send the ACK together with the first data. In Linux this can be achieved by explicitly disabling quick ack before connecting:
int off = 0;
setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &off, sizeof(off));
connect(fd,...)

https://stackoverflow.com/a/6440364

Turn the SO_LINGER socket option on and set the linger time to 0 seconds. This will cause TCP to abort the connection when it is closed, flush the data and send a RST. See section 7.5 and example 15.21 in UNP.

This option specifies how the close function operates for a connection-oriented protocol , By default, close returns immediately, but if there is any data still remaining in the socket send buffer, the system will try to deliver the data to the peer.
if l_onoff is nonzero and l_linger is zero, TCP aborts the connection when it is closed (pp. 1019–1020 of TCPv2). That is, TCP discards any data still remaining in the socket send buffer and sends an RST to the peer, not the normal four-packet connection termination sequence

import socket
import select
import struct
import time

s = socket.socket()
s.setblocking(0)
s.setsockopt(socket.SOL_TCP, socket.TCP_QUICKACK, 0)
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
                         struct.pack('ii', 1, 0)) # when socket close, discard pending writes and send rst
try:
    s.connect(("10.197.128.110", 8081))
except: # EInprogress
    pass
select.select([s], [], [], 0.1)
s.close() # with the help of linger, close will send rst packet

你可能感兴趣的:(Use TCP_QUICKACK and SO_LINGER to eliminate the 3rd packet in tcp handshake)