目录
一.再谈端口号
1.端口号定义
2.端口号范围划分
(1)一共有 2^16 个端口
(2)认识知名端口号(Well-Know Port Number)
3.端口号和进程就是K V关系
4.netstat
(1)示例1: n 拒绝显示别名,能显示数字的全部转化成数字
(2)示例2: l 仅列出有在 Listen (监听) 的服务状态
(3)示例3: p 显示建立相关链接的程序名
5.pidof
二.UDP协议
1.UDP协议端格式
(1)UDP协议结构
(2)报头就是 带有位段的结构体 :
(3)添加报头的本质,其实就是拷贝对象
2.UDP的特点
3.面向数据报
4.UDP的缓冲区
5.UDP使用注意事项
6.基于UDP的应用层协议
三.TCP协议
1.TCP定义
2.TCP协议段格式
①如何封装和解包:
②如何分用
(1)详细介绍TCP协议段格式
(2)报文也是有类别的
(3)32位序号保证按序到达——URG
①32位序号保证按序到达到达:
②URG紧急指针标记位与紧急指针:
③URG应用场景——用来 获取服务器/主机 状态
3.可靠性问题:
(1)什么是不可靠:丢包,乱序,校验失败。。
(2)怎么确认一个报文是丢了还是没丢? ?(确认应答机制)
4.确认应答(ACK)机制
(1)32位序号/32位确认号
(2)为什么TCP报头有32位序号和32位确认号两组序号?常考
5.tcp的发送和接收缓冲区
(1)tcp有发送和接收缓冲区
(2)16位窗口大小——流量控制策略
(3)tcp正文长度由应用层决定
四.TCP三次握手
1.介绍
2.为什么要TCP三次握手
3.如何理解连接呢?
4.为什么是三次?
(1)三次握手一定能成功吗?
(2)为什么不是一次/二次握手?
(3)为什么是三次?
5.丢包解决——超时重传机制
(2)重复收到数据, 序列号可去重
(3)如果超时的时间如何确定?
五.连接管理机制
2.listen的第2个参数
3.状态
(1)CLOSE_WAIT 半关闭状
(2)TIME _WAIT
一.再谈端口号
1.端口号定义
2.端口号范围划分
(1)一共有 2^16 个端口
(2)认识知名端口号(Well-Know Port Number)
cat /etc/services

我们自己写一个程序使用端口号时, 要避开这些知名端口号。
3.端口号和进程就是K V关系
4.netstat
(1)示例1: n 拒绝显示别名,能显示数字的全部转化成数字
(2)示例2: l 仅列出有在 Listen (监听) 的服务状态

(3)示例3: p 显示建立相关链接的程序名
普通用户无法查看到建立相关链接的PID和程序名,只有root权限才能查看到
5.pidof
二.UDP协议
1.UDP协议端格式
(1)UDP协议结构
前8个字节是 UDP报头;剩下是报文
16位源端口号:自己的进程的端口号
16位目的端口号:要访问的目标进程的端口号
(2)报头就是 带有位段的结构体 :

(3)添加报头的本质,其实就是拷贝对象
把对象的成员变量填好,通过sizeof(udp_header)的大小拷贝进二进制,再强转成udp_header(udp_hdr)类型

2.UDP的特点

3.面向数据报
数据报:报文和报文之间有明显边界,因为有16位UDP长度。
4.UDP的缓冲区
5.UDP使用注意事项
6.基于UDP的应用层协议
三.TCP协议
1.TCP定义
2.TCP协议段格式
①如何封装和解包:
②如何分用
(1)详细介绍TCP协议段格式


(2)报文也是有类别的




URG:紧急指针标记位。作用:该报文忽略序号,被上层直接读取处理。(该报文叫紧急指针报文)详情见三—>2—>(3)

若最后的ACK丢失,则客户端不知道仍认为建立好连接了,则会继续发消息;服务器在未收到ACK时也意识到了这种问题,为了避免这种情况,服务器在未收到ACK时会连接重置,重新发送SYN+ACK应答,同时也把RST置为1
(3)32位序号保证按序到达——URG
①32位序号保证按序到达到达:
报文在发送的时候,是可能乱序到达的。这是不可靠的一种。
需要让我们的报文进行按序到达,如何做到? ——32位序号保证按序到达。为报文标序号,接收缓冲区收到后排序即可。
②URG紧急指针标记位与紧急指针:
如果数据是必须在TCP中进行按序到达的话,也就是说如果有一些数据优先级更高,但是序号较晚,无法做到数据被有限紧急处理!
解决方案:使用 URG紧急指针标记位, URG标记为1,将优先级更高的报文忽略序号,被上层直接读取处理。(该报文叫紧急指针报文)
16位紧急指针:指向紧急指针报文的偏移量。紧急指针报文只能有一个字节
③URG应用场景——用来 获取服务器/主机 状态
客户端向服务器发数据,服务器可能因某种原因(例如内存不足)而无法接收消息或接收消息缓慢,这种情况下客户端想获知服务器的状态,就发送报文 URG紧急指针标记位 标为1,此时server在非常困难的情况下依旧优先接收了指向的一字节,在服务器内部通过已设置的某种逻辑得出一个状态码20(假设),通过 URG紧急指针标记位 把指向的一字节返回给客户端,客户端收到20状态码得知服务器无法正常工作原因是“内存不足”,再通知工作人员即可。

3.可靠性问题:
(1)什么是不可靠:丢包,乱序,校验失败。。
(2)怎么确认一个报文是丢了还是没丢? ?(确认应答机制)
答:我们如果收到了应答,我们确认是没丢,否则就是不确定。可靠性是指我们发出去的报文得到了对方应答是可靠的,没被应答的不能保证可靠。
详细解释:我们发出去的消息,我们如何得知对方是否收到?——只要得到对方的应答就意味着我刚刚发的消息对方100%收到了!
在长距离交互的时候,永远有一条最新的数据是没有应答的,所以没有百分之百可靠的协议!!但是可以做到局部百分之百可靠。
但是:只要发送的消息有对应的应答,我们就认为我们发送的消息,对方是收到的! !
确认应答机制保证了数据能被对方收到的问题
4.确认应答(ACK)机制
(1)32位序号/32位确认号
建立一个共识: tcp进行通信的时候,发送出去的报文一定会携带tcp报头!
解释下图:客户端发送一个有效载荷时一定是携带tcp报头的,并且数据都已经填好。假设随机生成的起始序号是1, 客户端发给服务器的整个报头+报文大小1000字节,则他占了1~1000序号,则32位序号就是1。服务器收到后为了应答客户端,则他会回复32位确认号是1001,它表示接收方已经收到了字节序号为 [1, 1000] 的数据,现在期望你发送字节序号为 1001 以及以后的数据。
32位序号/32位确认号:序号标定一个报文的编号;确认号标定 该确定号之前的报文全部收到,之后的报文从该确定好下一个序号开始发 ,保证双向的全双工的确认应答机制。
例:服务器收到6个报文,32位序号分别是1,2,3,5,6,7,响应时返回给客户端的确认序号应该填4。解释:确认号是为了告诉客户端特定序号之前的报文全部收到,因为这里没收到4号报文,所以填4是告诉客户端4之前的报文全部收到,4没收到,客户端要从4号开始重新发。
(2)为什么TCP报头有32位序号和32位确认号两组序号?常考
因为TCP协议是全双工的,我在给你发消息的同时,我也可以收消息。
解释:如果服务器想给你应答(填充确认序号),并且同时给你发消息(携带自己的序号)呢?——客户端给服务器发送“你吃饭了吗?”(填充32位序号),服务器给客户端发送应答“我吃饭了”(填充32位确认序号),同时发出“那你吃饭了吗?”(填充自己的32位序号)
客户端用序号和对方的确认序号保证了从左向右的可靠性,服务器用自己的序号和对方的确认序号保证了从右向左的可靠性。这样保证了双向的全双工的确认应答机制。
(3)
5.tcp的发送和接收缓冲区
(1)tcp有发送和接收缓冲区
IO类函数.本质其实都是拷贝函数
我们用write/send函数把数据拷贝到内核缓冲区后,tcp会在合适时候进行发送。内核缓冲区的数据什么时候发,发多少,出错了怎么办,要不要添加提高效率的策略——是由OS内的TCP自主决定的,所以TCP叫做传输控制协议!
上图可知,读写缓冲区用一个文件描述符业互不影响,可以说明 TCP通信是全双工的! !
(2)16位窗口大小——流量控制策略
在客户端向服务器发送数据包时,如果发送的太快了,导致server来不及接收怎么办?
——需要让client知道server的接受能力!
1.哪一个指标表示 server的接受能力呢? ——接收缓冲区剩余空间的大小!
2. client怎么知道? ? ——发送都会有应答!应答本质就是要包含TCP报头,tcp报头可以有保存server接受能力的属性字段,叫做 16位窗口大小
3.server给client发报文,填充的窗口大小,填充的是自己的接收缓冲区剩余空间大小。
4. client——>server, server——> client,两个方向都是一样的
总结:双方的发送缓冲区基于得知对方接收缓冲区接收能力的条件下进行数据通信,根据对方每次应答中不断更新的窗口大小定期向对方发送合适的数据大小,这种策略就叫做流量控制策略。流量控制策略是双向的!
(3)tcp正文长度由应用层决定
tcp流式服务,所以没必要考虑正文长度,正文长度是需要应用层自己定协议的,比如我们写的encode和decode对整个序列化之后的字符串 9\r\n100 + 200\r\n 进行提取长度
四.TCP三次握手
1.介绍
TCP三次握手:是 SYN,SYN+ ACK,ACK。SYN建立连接,SYN+ ACK 建立连接并确认连接,即应答,第三次ACK是客户端应答。
图中的线是斜的表明是要花时间的
2.为什么要TCP三次握手
——因为tcp是面向连接的。需要连接就用,udp肯定不用吧。
3.如何理解连接呢?
——大量的连接,OS就需要管理这些连接,如何管理? ?——先描述,在组织。建立连接结构体对象,再把结构体维护起来。维护连接是有成本的,花时间,花空间。
4.为什么是三次?
(1)三次握手一定能成功吗?
——不一定。tcp虽然是保证可靠性的,保证在通信时发送给对方的数据保证对方能收到。但不保证连接建立一定成功,是可以失败的。
(2)为什么不是一次/二次握手?
——不能。一次握手是指只发一个SYN就立马建立连接,这样容易受到攻击(SYN洪水)。SYN洪水:如果一个客户端故意发送很多SYN,则服务器需要维护对应的连接结构体,这样服务器会瞬间被占满,则导致正常连接无法连接。二次握手同理(SYN,SYN+ ACK)。多次发送SYN,服务器尽管多向客户端发送了ACK确认,但是客户端可以直接丢弃,没有任何代价的情况下让服务器维护一堆结构体从而打满。
(3)为什么是三次?
——理由1:奇数次握手可以把连接建立成功后最后一个报文丢掉的成本嫁接给客户端,最后一次确认由服务端来做,保证客户端比服务器先建立连接。如果一个客户端故意发送很多SYN,服务器收到后,短暂半连接维护连接结构体,然后返回给客户端SYN+ ACK 。客户端必须接收并返回ACK给服务器让服务器确认,如果客户端必不接收就无法发送ACK给服务器,服务器没收到则视为连接失败,服务器清除短暂半连接结构体;如果客户接收并返回ACK给服务器,则客户端也必须自己维护连接结构体,则服务器会拉客户端下水,则一个客户端想 SYN洪水 占满一个服务器很难,因为客户端的资源也在不断减少。这样就保证至少一个客户端想 SYN洪水 干翻一个服务器很难(以较小成本让服务器不那么容易被攻击到),但是也不是完全能避免,如果非常多客户端同时攻击也是不行的。
理由2:客户端和服务器都各自进行了一堆IO操作,这样以最小代价验证了全双工。
那客户端半链接不行?
5.丢包解决——超时重传机制
(2)重复收到数据, 序列号可去重

(3)如果超时的时间如何确定?
五.连接管理机制
四次挥手:一方向另一方发送FIN断开连接请求,对方ACK应答,对方同理,一个close对应一对挥手,共4次挥手。(特殊情况三次挥手:客户端向服务器发送FIN断开连接请求,对方ACK应答并且正好FIN置1也想断开,客户端在发送第三次ACK,这就是三次)
2.listen的第2个参数
list的第二个参数,叫做底层的全连接队列的长度,算法是: n+1, (n是用户传入的值)表示在不accept的情况你最多能够维护多少个链接。例如传2,就表示在不accept的情况最多能够维护3个链接,剩下的客户端请求的连接以半连接保持,当有全连接退出时,这个半连接才会变成全连接。
全连接维护的意义!
3.状态
(1)CLOSE_WAIT 半关闭状
无论是否accept,客户端只要close关闭,但服务器未close关闭,服务器一方就一直是 CLOSE_WAIT 状态(一方close,另一方未close,即半关闭状态):
(2)TIME _WAIT
连接保持的状态下直接关闭服务器,服务器就成了主动关闭的一方,主动关闭的一方最终就会进入 TIME _WAIT(4次挥手已完成),过一会儿连接就会自动关闭