零 实验平台
window10 + wireshark
一 实验代码
TCP 服务器端:
from socket import *
serverport = 12003
serversocket = socket(AF_INET, SOCK_STREAM)
serversocket.bind(('', serverport))
k = serversocket.listen(1)
print(k)
print('The server is ready to receive')
while True:
connectionsocket, addr = serversocket.accept()
sentence = connectionsocket.recv(1024)
capitalizedsentence = sentence.upper()
connectionsocket.send(capitalizedsentence)
connectionsocket.close()
TCP 客户端:
from socket import *
serverName = '10.133.255.254'
serverport = 12003
clientsocket = socket(AF_INET, SOCK_STREAM)
clientsocket.connect((serverName, serverport))
sentence = input('Input lowercase sentence: ')
clientsocket.send(sentence.encode())
modifiedSentence = clientsocket.recv(1024)
print('From server:', modifiedSentence)
clientsocket.close()
input('???')
二:抓包分析
Ⅰ:当server未开启时
可以看到,client发送了连接请求包,server没有开启12002端口程序,所以server给client发送了RST复位包。后面的包都是client重传,server发送RST复位包。
可以看出,在window上,TCP重传等待时间是0.5s。严重怀疑第一个定时器是0.5s
看看连接请求包的具体内容:
①源端口 57638 在报文里是e1 26 大端mode
②目的端口12002 2e e2 大端mode
③序号 0 (wireshark显示的是相对序号) 在报文里 0e 65 51 d3
④确认号 0
⑤首部长度 8 在报文里80 8*4bytes = 32bytes
⑥标志位 只有SYN =1 在报文里 0x002
⑦接收窗口 8192 在报文里 20 00
⑧检验和 cd d8
再来分析RST复位包
①源端口12002 在报文里2e e2
②目的端口 57638 在报文里 e1 26
③序号 1 (wireshark显示的是相对序号) 在报文里 00 00 00 00
④确认号 1 在报文里 0e 65 51 d4 加了一,毕竟TCP是只要有数据,序号就要加1 (但这不影响后面的传包)
⑤首部长度 5 在报文里50 5*4bytes = 20bytes
⑥标志位 只有ACK=1,RST=1 在报文里 0x014
⑦接收窗口 0 在报文里 00 00
⑧检验和 2e 98
再来分析重传包
①源端口 57638
②目的端口12002
③序号 0 (wireshark显示的是相对序号) 在报文里 0e 65 51 d3 (没变)
④确认号 0
⑤首部长度 8 在报文里80 8*4bytes = 32bytes
⑥标志位 只有SYN =1 在报文里 0x002
⑦接收窗口 8192 在报文里 20 00
⑧检验和 cd d8
尴尬了,和请求包是一样的,这也合情合理。(+_+)?
结论
一:在windows上,TCP第一次重传时间是0.5s
二:无论是端口,还是序号等等,都是用大端。所以socket编程时,你要从套接字中获取port或ip时,要使用相关函数进行大小端转换d=====( ̄▽ ̄*)b
NBO network byte order | 大端 |
---|---|
HBO host byte order | 小端 |
in arpe/init.h
函数 | 作用 |
---|---|
htonl | host to network long |
ntohl | network to host long |
htons | host to network short |
ntohs | network to host short |
三:RST包的接收窗口是0
四:RST包虽然会使确认号+1,但是不会改变TCP流中的序号。
2 开启server,正常TCP通话
TCP三次握手
第一个包
①源端口 58525
②目的端口 12003
③序列 0 在报文里 d0 b8 4b 8b
④确认号 0
⑤标志位 SYN =1
⑥接收窗口 8192
⑦检验和 0x7e 24
⑧在tcp选项里:设置了最大窗口 1460字节
和window scale : 8
第二个包
①源端口 12003
②目的端口 58525
③序列 0 在报文里 e3 ca 0b 64
④确认号 1 在报文里 d0 b8 4b 8c
⑤标志位 SYN =1,ACK=1 在报文里0x012
⑥接收窗口 8192
⑦检验和 0x8f 34
⑧在tcp选项里:设置了最大窗口 1380字节
和window scale : 8
第三个包
①源端口 58525
②目的端口 12003
③序列 1 在报文里 d0 b8 4b 8c
④确认号 1 在报文里 e3 ca 0b 65
⑤标志位 ACK=1 在报文里0x010
⑥接收窗口 16384
⑦检验和 0xef 77
数据传递
①源端口 58525
②目的端口 12003
③序列 1 在报文里d0 b8 4b 8c
④确认号 1 在报文里 e3 ca 0b 65
⑤标志位 PSH =1,ACK=1 在报文里0x018
⑥接收窗口 16384 64*(2^8)(后面总结写)
⑦检验和 0x2a a5
⑧数据 61626364 ->对应为abcd
第二个包
①源端口 12003
②目的端口 58525
③序列 1 在报文里 e3 ca 0b 65
④确认号 5 在报文里 d0 b8 4b 90
⑤标志位 PSH =1,ACK=1 在报文里0x018
⑥接收窗口 65792 257*(2^8)
⑦检验和 0x6a 20
⑧数据 61626364 ->对应为abcd
四次握手结束连接
在代码里,是server主动关闭连接,所以与书上的情况相反
第一个包
①源端口 12003
②目的端口 58525
③序列 5 在报文里 e3 ca 0b 69
④确认号 5 在报文里 d0 b8 4b 90
⑤标志位 FIN =1,ACK=1 在报文里0x011
⑥接收窗口 65792 257*(2^8)
⑦检验和 0xee ad
第二个包
①源端口 58525
②目的端口 12003
③序列 5 在报文里 d0 b8 4b 90
④确认号 6 在报文里 e3 ca 0b 6a
⑤标志位 ACK=1 在报文里0x010
⑥接收窗口 16384 64*(2^8)
⑦检验和 0xef 6e
第三个包
①源端口 12003
②目的端口 58525
③序列 1 在报文里 d0 b8 4b 90
④确认号 5 在报文里 e3 ca 0b 6a
⑤标志位 FIN=1,ACK=1 在报文里0x011
⑥接收窗口 16384 64*(2^8)
⑦检验和 0xef 6d
第四个包
①源端口 12003
②目的端口 58525
③序列 1 在报文里 e3 ca 0b 6a
④确认号 5 在报文里 d0 b8 4b 91
⑤标志位 ACK=1 在报文里0x010
⑥接收窗口 65792 257*(2^8)
⑦检验和 0xee ac
结论
一:在选项里maxsize window 定义了最大窗口值 MSS
window scale 定义了windos的伸缩值 Window scale,具体是用当前窗口值 乘以 (2^Window_scale)
由于网络变化多,情况难以分析。但TCP又保证了可靠数据传输。TCP很复杂。在计算机网络里,只学了TCP最为精华的部分。想要深入TCP,还是要看TCP详解,加油(ง •_•)ง