传输层之TCP与UDP协议
| TCP与UDP都是用来规定通信方式的 |
| ps:不遵循上述协议也可以通信 只不过遵循了更合规合法合理!!! |
| 1.TCP协议(重要) |
| 三次握手建链接 |
| 1.TCP协议也称为可靠协议(数据不容易丢失) |
| 造成数据不容易丢失的原因不是因为有双向通道 而是因为有反馈机制 |
| 给对方发消息之后会保留一个副本 直到对方回应消息收到了才会删除 |
| 否则会在一定的时间内反复发送 |
| 2.洪水攻击 |
| 同一时间有大量的客户端请求建立链接 会导致服务端一致处于SYN_RCVD状态 |
| 3.服务端如何区分客户端建立链接的请求 |
| 可以对请求做唯一标识 |
| 四次挥手断链接 |
| 1.四次不能合并为三次 |
| 因为中间需要确认消息是否发完(TIME_WAIT) |
| """ |
| 三次握手和四次挥手也可以看成是小情侣谈恋爱的过程 |
| 三次握手 |
| 四次挥手 |
| """ |
| ps:课下可以深入研究一下TCP图片上每个状态的具体情况 |
| |
| 2.UDP协议 |
| 也称之为数据报协议、不可靠协议 |
| 早期的QQ使用的是纯生的(没有加任何额外功能)UDP协议 |
| 现在的QQ自己添加了很多技术和功能 |
| 使用UDP的原因就是因为很简单 快捷 粗暴 只要指定对方的地址就可以发消息了 |
| """ |
| TCP我们可以看成是打电话:双方你侬我侬 |
| UDP我们可以看成是发短信:只要发了就行 不管对方看不看 |
| """ |



之所以称之为三次握手就是因为中间的服务端的同意,和请求合并成了一次请求

三次握手状态内容
| 所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。 |
| 三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时。将触发三次握手。 |
| 第一次握手(SYN=1, seq=x): |
| 客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号(Sequence Number)字段里。 |
| 发送完毕后,客户端进入 SYN_SEND 状态。 |
| 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1): |
| 服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。 发送完毕后,服务器端进入 SYN_RCVD 状态。 |
| 第三次握手(ACK=1,ACKnum=y+1) |
| 客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1 |
| 发送完毕后,客户端进入 ESTABLISHED 状态,当服务器端接收到这个包时,也进入 ESTABLISHED 状态,TCP 握手结束。 |
四次挥手
挥手必须是四次,中间的两次不能合并成一次,原因就在于需要检查是否还有数据需要给对方发送.

| TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),也叫做改进的三次握手。客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行 close() 操作即可产生挥手操作。 |
| 第一次挥手(FIN=1,seq=x) |
| 假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为1的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。 |
| 发送完毕后,客户端进入 FIN_WAIT_1 状态。 |
| 第二次挥手(ACK=1,ACKnum=x+1) |
| 服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。 |
| 发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。 |
| 第三次挥手(FIN=1,seq=y) |
| 服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为1。 |
| 发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK。 |
| 第四次挥手(ACK=1,ACKnum=y+1) |
| 客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待可能出现的要求重传的 ACK 包。 |
| 服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。 |
| 客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。 |
| |
应用层
| 应用层相当于是程序员自己写的应用程序 里面的协议非常的多 |
| 常见的有:HTTP、HTTPS、FTP |
| ps:后续框架部分再做介绍 |
socket模块

Socket通信
Socket是应用层与TCP/IP协议簇通信的中间抽象层,是一组接口。在设计模式中其实就是门面模式。Socket将复杂的TCP/IP协议簇隐藏在接口后面,对于用户而言,一组接口即可让Socket去组织数据,以符合指定的协议。
socket 其实就是操作系统提供给程序员操作「网络协议栈」的接口,说人话就是,你能通过socket 的接口,来控制协议找工作,从而实现网络通信,达到跨主机通信。
socket代码简介
| import socket |
| |
| |
| """ |
| 以后要养成查看源码编写代码的思路 |
| """ |
| |
| server = socket.socket() |
| |
| server.bind(('127.0.0.1', 8080)) |
| |
| server.listen(5) |
| |
| sock, addr = server.accept() |
| print(sock, addr) |
| |
| data = sock.recv(1024) |
| print(data.decode('utf8')) |
| sock.send('尊敬的客人 您说什么就是什么 一切按照您的要求来'.encode('utf8')) |
| |
| sock.close() |
| |
| server.close() |
| |
| |
| |
| |
| import socket |
| |
| |
| |
| client = socket.socket() |
| |
| client.connect(('127.0.0.1', 8080)) |
| |
| client.send('大爷有钱 把你们店最好的给我叫出来'.encode('utf8')) |
| |
| data = client.recv(1024) |
| print(data.decode('utf8')) |
| |
| client.close() |
代码优化
| 1.聊天内容自定义 |
| 针对消息采用input获取 |
| 2.让聊天循环起来 |
| 将聊天的部分用循环包起来 |
| 3.用户输入的消息不能为空 |
| 本质其实是两边不能都是recv或者send 一定是一方收一方发 |
| 4.服务端多次重启可能会报错 |
| Address already in use 主要是mac电脑会报 |
| 方式1:改端口号 |
| 方式2:博客里面代码拷贝即可 |
| 5.当客户端异常断开的情况下 如何让服务端继续服务其他客人 |
| windows服务端会直接报错 |
| mac服务端会有一段时间反复接收空消息延迟报错 |
| 异常处理、空消息判断 |
半连接池的概念
| server.listen(5) |
| |
| 当有多个客户端来链接的情况下 我们可以设置等待数量(不考虑并发问题) |
| 假设服务端只有一个人的情况下 |
| |
| 在测试半连接池的时候 可以不用input获取消息 直接把消息写死即可 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现