文章目录
一、传输层概述
1、传输层的功能
传输层主要工作在终端设备
传输层:管理端到端的通信连接,解决跨设备跨网络的进程与进程之间的通信
2、端口:
- 使用端口(Port)来标记不同的网络进程
- 端口使用16比特位表示(0~65535)
FTP | HTTP(网站) | HTTPS(安全) | DNS | TELNET |
---|---|---|---|---|
21 | 80 | 443 | 53 | 23 |
3、协议
协议呈现中间窄,两端大的沙漏形状
二、UDP协议详解
- UDP(User Datagram Protocol:用户数据报协议)
- UDP是一个非常简单的协议
- 数据报是由应用层传给传输层的完整数据
- 传输不会对它进行任何操作,直接封装在协议中传输出去,不合并、不拆分
1、UDP所在位置
其中:UDP数据报的数据指的就是数据报
UDP首部
16位源端口号 | 16位目的端口号 | 16位UDP长度 | 16位UDP校验和 |
---|---|---|---|
包括数据在内的长度(最小值为8字节,只包含头部) | 检验传输中是否出错 |
-----------------------------UDP数据------------------------
2、UDP协议特点
- UDP是无连接协议
- 无连接:在发送消息之前不需要进行连接,想发送消息则直接将消息发送过去
- UDP不能保证可靠的交付数据
- 不能保证可靠:无法保证数据在网络中是否丢失
- UDP是面向报文传输的
- 报文:应用层传过来的数据报
- 面向报文:传输层不对报文进行合并拆分,只加上头部直接发送
- UDP没有拥塞控制
- 拥塞:就像堵不堵车一样,网络中传输数据比较多
- 没有拥塞控制:UDP不管网络中是否拥塞,都会尽力将数据报发送出去
- UDP的首部开销很小
- UDP首部长度只有8字节
三、TCP协议
1、TCP协议详解
- TCP(Transmission Control Protocol:传输控制协议)
- TCP协议是计算机网络中非常复杂的一个协议
1)TCP协议的结构
i、TCP协议所在位置
ii、TCP协议的头部
除去TCP可选和填充,TCP头部固定有20字节
序号:
- 有32位,长度为0~2^32-1
- 一个字节一个序号
- 这里的序号指数据首字节序号
确认号:
- 有32位,长度为0~2^32-1
- 一个字节一个序号
- 期望收到数据的首字节序号。 例如,现在已经收到了首字节序号为501的一串长度为100的字节流,则接下来就希望收到首字节序号为601的字节流,这里的确认号为601
- 确认号为N:表示N-1序号的数据都已经收到
数据偏移:
- 占4位:0~15,单位为:32字节
- 即4位每一位代表32字节
- 数据偏移首部的距离
- 根据头部中TCP选项确定,因此头部的长度为20~60字节
TCP标记:
- 占6位,每位各有不同意义
标记 | 含义 |
---|---|
URG | Urgent:紧急位,URG=1,表示紧急数据 |
ACK | Acknowledgement:确认位,ACK=1,确认号才生效 |
PSH | Push:推送位,PSH=1,尽快把数据交付给应用层 |
RST | Reset:重置位,RST=1,重新建立连接 |
SYN | Synchronization:同步位,SYN=1表示连接请求报文 |
FIN | Finish:终止位,FIN=1 表示释放连接 |
窗口:
- 占16位:0~2^16-1
- 窗口指明允许对方发送的数据量
紧急指针:
- 紧急数据(URG=1)
- 指定紧急数据在报文的位置
TCP选项: - 最多40字节
- 支持协议未来的发展
2、TCP协议的特点
- TCP是面向连接的协议
- 面向连接:需要先创建链接,再进行通信
- TCP的一个连接有两端(点对点通信)
- TCP提供可靠的传输服务
- TCP协议提供全双工的通信
- 全双工:建立好连接的双方可以同时在连接中发送消息。比如打电话时双方都可以说话
- TCP是面向字节流的协议
- 字节流:进入进程或流出进程的字节序列
- 面向字节流:TCP协议可能会对数据报进行合并拆分,携带数据报的一部分字节,下一个TCP协议携带数据报的另一部分字节
2、可靠传输的基本原理
1)停止等待协议
通过超时重传来保证可靠传输
超时定时器:每发送一个消息,都需要设置一个定时器
- 停止等待协议是最简单的可靠传输协议
- 停止等待协议对信道的利用率不高
i、无差错的情况:
将交流的双方简化为发送方和接收方
发送方:发送消息1后就停止发送消息,等待接收方的确认消息1;收到确认消息1后发送消息2,停止发送消息,等待确认消息2……,一直按照停止等待的方式发送消息
接收方:停止发送确认消息,等待发送方的消息,收到消息1后,发送确认消息1,然后停止发送,等待发送方发送新的消息……,也是按照停止等待的方式接收消息
ii、出差错的情况
1. 发送方的消息在发送过程中丢失:
此时发送方发送消息1后,在等待一段时间后还没收到接收方的确认消息1,会再次发送消息1 ,即超时重传
2. 接收方发送的确认消息丢失:
发送方在发送完消息1后,等待一段时间后还没收到确认消息1,会再次发送消息1,同样为超时重传
3. 应该在这次收到的确认消息在很久以后才收到:
发送方没收到确认消息1,等待一段时间后,再次发送消息1,同样为超时重传
2)连续ARQ协议
- ARO(Automatic Repeat reQuest:自动重传请求)
- 滑动窗口:比如批量发送了1~6序列号的消息,但是只收到1和2序列号的消息,此时滑动窗口就为2,窗口向右滑动2个位置,下一次发送的首节序列号为3
- 累计确认:接收方收到了1~6序列号的消息,只发送序列号5的确认消息,就表示序列号5之前的所有序列号都已经收到了,不需要确认,下次接收序列号为6开头的消息,由此提升网络的效率
3、TCP协议的可靠传输
- TCP的可靠传输基于连续ARQ协议
- TCP的滑动窗口以字节为单位
1)前面的窗口已经确认,可以往前推动的情况
2)确认的序列号中,首字节序列号还没收到的情况
此时虽然25和27已经收到,但是让不能往前推动,因为23、24还没收到,此时发送方等待一段时间后,没收到确认消息,再次从23开始重传
3)选择重传
根据上述问题,进行选择重传来解决
- 选择重传需要指定需要重传的字节
- 重传的字节一般为一个片段,不是一个字节,所以指定的是需要重传的边界
- 需要重传的自己片段的首字节序列号和尾字节序列号存储在TCP选项中
- 每一个字节都有唯一的32位序号
4、TCP协议的流量控制
TCP协议特有的功能
- 流量控制指让发送方发送速率不要太快
- 流量控制是使用滑动窗口来实现的
通过窗口大小控制对方发送速率
最后在接收方有空余窗口时向发送方发送空余的窗口数1000这条消息丢失了,此时接收方和发送方进入一个死锁局面,由于TCP可靠传输只针对的是确认消息和发送消息的序列号,所以关于窗口的特殊消息是不做可靠传输的,不会超时重传,因此这里需要一个坚持定时器,解决这个死锁局面。
坚持定时器:
- 当接收到窗口为0的消息,则启动坚持定时器
- 坚持定时器每隔一段时间发送一个窗口探测报文,查看窗口是否增加
5、TCP协议的拥塞控制
1)为什么会发生拥塞:
- 一条数据链路经过非常多的设备
- 数据链路中各个部分都有可能成为网路传输的瓶颈
2)流量控制和拥塞控制的对比:
- 流量控制考虑点对点的通信量的控制
- 拥塞控制考虑整个网络,是全局性的考虑
3)关于拥塞控制的算法
i、慢启动算法
- 由小到大逐渐增加发送数据量
- 每收到一个报文确认,就加一,在已收到的数据量上加一作为下次发送的数据量
- 比如1、2、4、8、16,以指数增长
- 增长到一定量时,不再增长,这个量称为慢启动阈值(ssthresh)
ii、拥塞避免算法
在发送的数据量到达慢启动阈值时,采用
- 维护一个拥塞窗口的变量,这个变量大于慢启动阈值
- 如果采用这个变量后,网络不拥塞,就试探将拥塞窗口调大
发送的数据量的增长图示
指数增长部分使用慢启动算法,到达慢启动阈值后,采用拥塞避免算法
6、TCP连接的三次握手
1)TCP连接使用到的TCP标记:
标记 | 含义 |
---|---|
ACK | Acknowledgement:确认位,ACK=1,确认号才生效 |
SYN | Synchronization:同步位,SYN=1 表示连接请求报文 |
FIN | Finish:终止位,FIN=1 表示释放连接 |
2)TCP三次握手过程:
第一次:发送方向接收方发送请求连接消息,消息序列号为x
第二次:接收方向发送方发送请求连接、确认连接消息,seq为本消息的序列号,ack为确认的消息的序列号加一,表示对seq=x已经确认
第三次:发送方向接收方发送确认连接消息,seq=x+1表示本消息的序列号,ack=y+1表示对seq=y的消息的确认
3)为什么发送方要发出第三个确认报文呢?
- 已经失效的连接请求报文传送到对方,引起错误
- 如果发送方发送的连接请求超时,发送方再次发送了同样的连接请求却很快收到接收方的确认消息,然后建立了连接;之后第一次发送的连接请求也到达接收方,接收方同样回复了确认连接,也要建立连接,由此引发网络错误
- 如果有第三次握手,接收方在收到发送方的确认后再连接,之后如果再有连接请求,在第二次握手发现,发送方已经建立了连接,就不会再理睬。
7、TCP连接的四次挥手
1)四次挥手过程
发送方的结束请求第二次等待阶段 (FIN-WAIT-2):等待接收方将自己的数据发送完
主动释放连接的一方在双方都确认释放连接之后还会有一个等待释放状态(等待计时器TIME-WAIT)
2)等待计时器:
- 等待时间为2MSL
- MSL(Max Segment Lifetime):最长报文段寿命
- MSL建议设置为2分钟
3)为什么需要等待2MSL:
- 最后一个报文没有确认
- 确保发送方的ACK可以到达接收方,同时2MSL也是报文的存活时间
- 2MSL时间没有收到,接收方会重发连接释放请求报文
- 确保当前连接的所有报文都已经过期
四、套接字与套接字编程
1、端口号
- 使用端口(Port)来标记不同的网络进程
- 端口(Port)使用16比特位表示(0~65535)
2、{IP:Port}组合称为套接字
- 套接字(Socket)是抽象概念,表示TCP连接的一端
- 通过套接字可以进行数据发送或接收
- 两个套接字可以唯一指定一个TCP的连接(TCP={Socket1:Socket2})
3、套接字编程(python)
1) 服务端套接字编程步骤(被动连接的一方):
- 创建套接字
- 绑定套接字:绑定为某个ip或端口
- 监听套接字
- 接收&处理信息
2) 客户端套接字编程(主动连接的一方):
- 创建套接字
- 连接套接字:连接服务端的套接字
- 发送消息
3)编程
服务端:
import socket
def server():
# 1、创建套接字
s=socket.socket()
host='127.0.0.1'
# IP地址,这里为回环地址
port=6666
# 2、绑定套接字
s.bind((host,port))
# 3、监听
s.listen(5)
# 4、发送消息
while True:
# 接收到的连接即为客户端,向客户端发送消息
c,addr=s.accept()
print('Connet Addr:',addr)
c.send(b'Welcome to my course.')
# 字符串前加b表示这是一个bytes对象,由于客户端接收的为bytes对象
c.close()
if __name__ == '__main__':
server()
客户端:
import socket
def client(i):
# 1、创建套接字
s=socket.socket()
# 2、连接套接字
s.connect(('127.0.0.1',6666))
print('Recv msg:%s,Clinet:%d'%(s.recv(1024),i))
s.close()
if __name__ == '__main__':
for i in range(10):
client(i)
先run服务端,再run客户端;
服务端结果:
D:\software\python\python.exe D:/工作学习/计算机网络/编程/套接字/服务端.py
Connet Addr: ('127.0.0.1', 37445)
Connet Addr: ('127.0.0.1', 37446)
Connet Addr: ('127.0.0.1', 37447)
Connet Addr: ('127.0.0.1', 37448)
Connet Addr: ('127.0.0.1', 37449)
Connet Addr: ('127.0.0.1', 37450)
Connet Addr: ('127.0.0.1', 37451)
Connet Addr: ('127.0.0.1', 37452)
Connet Addr: ('127.0.0.1', 37453)
Connet Addr: ('127.0.0.1', 37454)
客户端结果:
D:\software\python\python.exe D:/工作学习/计算机网络/编程/套接字/客户端.py
Recv msg:b'Welcome to my course.',Clinet:0
Recv msg:b'Welcome to my course.',Clinet:1
Recv msg:b'Welcome to my course.',Clinet:2
Recv msg:b'Welcome to my course.',Clinet:3
Recv msg:b'Welcome to my course.',Clinet:4
Recv msg:b'Welcome to my course.',Clinet:5
Recv msg:b'Welcome to my course.',Clinet:6
Recv msg:b'Welcome to my course.',Clinet:7
Recv msg:b'Welcome to my course.',Clinet:8
Recv msg:b'Welcome to my course.',Clinet:9
4、网络套接字与域套接字
网络套接字:
无论是否需要跨网络,数据都会经过协议栈
域套接字:
使用S开头的域套接字文件进行通信,不需要经过协议栈
所以:
如果是单机通信,推荐使用域套接字,跨网络通信使用网络套接字