TCP三次握手和自连接的条件和缺点

详解三次握手

在这里插入图片描述
在这里插入图片描述
为什么 SYN 段不携带数据却要消耗一个序列号呢?
记住:
• 不占用序列号的段是不需要确认的,比如纯 ACK 包
• SYN 段需要对方的确认,需要占用一个序列号
• 凡是消耗序列号的 TCP 报文段,一定需要对端确认。如果这个段
没有收到确认,会一直重传直到达到指定的次数为止。

三次握手第二步:服务端回复 SYN + ACK

服务端收到客户端的 SYN 段以后,将 SYN 和 ACK 标记都置位
「序列号」存放服务端自己的序列号
「确认号」字段指定了对端(客户端)下次发送 段的序号,这里等于客户端 ISN 加一
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三次握手中的状态变迁

在这里插入图片描述

如果客户端发出去的 SYN 包,服务端⼀直没有回 ACK 会发⽣什么?

客户端重传 SYN 的次数由什么决定?

重传总时间:63s = 1s+2s+4s+8s+16s+32s
$ sysctl -a | grep tcp_syn_retries
net.ipv4.tcp_syn_retries = 6
在这里插入图片描述
在这里插入图片描述

TCP ⾃连接:⼀个看似 Bug 的现象

源端⼝号和⽬标端⼝号都是⾃⼰可能吗?
测试脚本

 self_connect.sh
while true
do
 telnet 127.0.0.1 50000
done

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如何解决⾃连接问题
• 让服务监听的端⼝与客户端随机分配的端⼝不可能相同即可
• 当出现⾃连接的时候,主动关掉连接

让服务监听的端⼝与客户端临时端⼝号不可能相同即可
客户端临时端⼝号的范围由 /proc/sys/net/ipv4/iplocalport_range
⽂件决定,只要服务端监控的端⼝号不在这个范围内就可以了。

当出现⾃连接的时候,主动关掉连接

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)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值