Conditions and disadvantages of TCP three-way handshake and self-connection

Detailed three-way handshake

insert image description here
insert image description here
Why does the SYN segment not carry data but consume a sequence number?
Remember:
• A segment that does not occupy a sequence number does not need to be confirmed, such as a pure ACK packet
• A SYN segment requires the confirmation of the other party and needs to occupy a sequence number
• All TCP segments that consume a sequence number must be confirmed by the other end. If
no acknowledgment is received for this segment, it will be retransmitted until the specified number of times is reached.

The second step of the three-way handshake: the server replies with SYN + ACK

After the server receives the SYN segment from the client, it sets both the SYN and ACK flags. The
"Serial Number" stores the server's own serial number.
The "Confirmation Number" field specifies the serial number of the peer (client) to send the next segment. Here Equal to client ISN plus one
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here

State transitions in the three-way handshake

insert image description here

What will happen if the server never returns an ACK to the SYN packet sent by the client?

What determines the number of times the client retransmits the SYN?

Total retransmission time: 63s = 1s+2s+4s+8s+16s+32s
$ sysctl -a | grep tcp_syn_retries
net.ipv4.tcp_syn_retries = 6
insert image description here
insert image description here

TCP self-connection: a phenomenon that seems to be a bug

Are both source and destination port numbers possible?
Test script

 self_connect.sh
while true
do
 telnet 127.0.0.1 50000
done

insert image description here
insert image description here
insert image description here
insert image description here
How to solve the self-connection problem
• The port that the service monitors is not the same as the port randomly assigned by the client
• When a self-connection occurs, actively close the connection

The port monitored by the service cannot be the same as the temporary port number of the client. The
range of the temporary port number of the client is
determined by the /proc/sys/net/ipv4/iplocalport_range file, as long as the port number monitored by the server is not in the This range is fine.

When a self-connection occurs, actively close the connection

func (sd *sysDialer) doDialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
    
    
 fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_STREAM, 0, "dial", sd.Dialer.Control)
 for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(fd, err) || spuriousENOTAVAIL(err)); i++ {
    
    
 if err == nil {
    
    
 fd.Close()
 }
 return newTCPConn(fd), nil
}
func selfConnect(fd *netFD, err error) bool {
    
    
 // If the connect failed, we clearly didn't connect to ourselves.
 if fd.laddr == nil || fd.raddr == nil {
    
    
 return true
 }
 l := fd.laddr.(*TCPAddr)
 r := fd.raddr.(*TCPAddr)
 return l.Port == r.Port && l.IP.Equal(r.IP)
}

Guess you like

Origin blog.csdn.net/qq_37247026/article/details/131539828