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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容