传输层之TCP与UDP协议

用于应用程序之间的通信

TCP与UDP都是用来规定通信方式的

​ 通信的时候可以随心所欲的聊 也可以遵循一些协议符合要求的聊

​ 随性所欲的聊:文字 图片 视频 小油腻话

​ 遵循一些协议:开头代尊称 首行空两格 只准用官腔 不能打情骂俏

PS:不遵循上述也可以通信 只不过遵循了更合规合法合理!

一、TCP协议(重要)

​ 三次握手建链接

​ 1.TCP协议也称为不可靠协议(数据不容易丢失)

​ 造成数据不容易丢失的原因不是因为有双向通道 而是因为有反馈机制

​ 给对方发小新之后会保留一个副本 直到对方回应消息收到了才会删除 否则会在一定时间内反复发送

​ 2.洪水攻击

​ 同一时间有大量的客户端请求建立链接 会导致服务端一直处于SYN_RCVD状态

​ 3.服务端如何区分客户端建立链接的请求

​ 可以对请求做唯一标识

我们先分析一下上图的英文都是啥东西。
SYN: 代表连接请求/连接接受 ACK: 确认 ack: 确认号 seq:序号 客户机下面有三个框里面分别是: CLOSED SYN-SENT ESTAB-LISHED
这代表主机的三个状态。
服务器下面有四个框分别是: CLOSED LISTEN SYN-RCVD ESTAB-LISHED
这代表服务器的四个状态。 CLOSED: 表示初始状态
CLOSED大家应该都知道是关闭的意思。
其实这里的CLOSED是关闭上次握手的东西。所以说CLOSED也就是初始化的意思。 LISTEN: 监听状态。表示服务器端的某个SOCKET处于监听状态。
所以说客户机是没有监听状态的,因为客户机是主动的一方。 SYN-SENT(客户机):
客户端调用连接,发送一个SYN请求建立一个连接,在发送连接请求后等待匹配的连接请求,此时状态为SYN_SENT。
简言之: 就是我(客户机)给你(服务器)发个消息说咱俩连接吧! 等待你确认和我连接的状态。 SYN-RCVD(服务器):
在收到客户机发来的连接请求和自己发送一个可以连接,等待对方对连接请求的确认的状态。
简言之: 我(服务器)同意和你(客户机)连接,我(服务器)等你(客户机)确认和我(服务器)说话的过程。 ESTAB-LISHED: 连接已经建立,两台机器正在传输数据的状态

​ 4.握手具体流程:

第一次握手:

客户机发送SYN=1, seq=x(随机的序号)  这时客户机进入SYN-SENT状态。
简言之: 我(客户机)发送一个连接请求,并说我这个报文的序号是x。 第二次握手:
服务器在收到客户机发来的SYN(连接请求)后,进入了SYN-RCVD状态。
服务器并发送:SYN=1(接受连接),ACK=1(确认),ack=x+1(客户机下次需要发送的报文序号) 和seq=y(服务器发送报文序号)
简言之:
我(服务器)答应连你,确认收到你的消息了。
下次你(客户机)给我发上次发送的报文(x)的后一个(即x+1.因为这个我有了 我要下一个)。我发送报文序号是y。 第三次握手:
客户机发送ACK=1,seq=x+1,ack=y+1
这时候客户机和服务器就开始进入传输数据(ESTAB-LISHED)的状态。

​ 四次挥手断链接

​ 1.四次为啥不能合并为三次

​ 因为中间需要确认消息是否发完(TIME_WAIT)

ESTAB-LISHED 连接建立  CLOSED 是关闭连接。

FIN-WAIT-1(客户机): FIN_WAIT_1状态是当客户机在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,
此时该客户机即 进入到FIN_WAIT_1状态.这时双方的连接都还没有断。 FIN-WAIT-2(客户机): 当对方(服务器)回应ACK报文后(即对方确认可以断开后),则进入到FIN_WAIT_2状态。
这时候是半连接状态。即客户机要求关闭连接,客户机不发送数据了
但服务器暂时还有点数据需要传送给客户机,稍后再关闭连接。 TIME_WAIT(客户机): 表示收到了服务器的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。
如果FIN_WAIT_1状态下,收到了对方同时带 FIN标志和ACK标志的报文时,
可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
简言之: 收到了对方(服务器)的断开标志(FIN)并确认(ACK)后,这时说明服务器确认断开连接且没有数据要传了,
客户机可以直接从FIN-WAIT-1到TIME-WAIT状态。 CLOSE-WAIT(服务器): 等待客户机发来的连接中断请求 ,服务器收到FIN后,
就发出ACK以回应FIN请求,服务器进入CLOSE_WAIT状态。 LAST_ACK(服务器): 服务器在发送FIN报文后,最后等待客户机的ACK报文。这个状态就是LAST_ACK。
当收到ACK报文后,服务器进入到CLOSED可用状态了。

​ 2.挥手具体流程:

第一次挥手:  客户机发送FIN=1,seq=u 之后进入了FIN-WAIT-1状态。
简言之:
客户机发送了一个断开连接的标志(FIN=1)。
并说这个报文的序号是u。接着客户机就进入了等待服务器确认的状态(FIN_WAIT-1)。 第二次挥手: 服务器发送ACK=1,seq=v,ack=u+1 后服务器进入了CLOSE-WAIT状态。客户机进入FIN-WAIT-2状态。
简言之:
服务器说我确认收到你的断开请求了(ACK=1),我发送的报文序号是v,
下次你(客户机)给我(服务器)发送u+1这个序号的报文。
服务器开始处理剩余的一些数据(CLOSE-WAIT)。客户机等服务器处理完剩余的数据给自己发送确认信号(FIN-WAIT-2) 第三次挥手: 服务器发送 FIN=1,ACK=1,seq=w,ack=u+1 随后服务器进入LAST-ACK状态。 简言之: 服务器给客户机发送了一个断开连接的标志(FIN=1),确认收到你的断开请求了(ACK=1),
我的发送的报文序号是w,你(客户机)下次给我(服务器)发送u+1这个序号的报文。
因为在此之前客户机并没有再次的给服务器发送报文。所以服务器给客户机要的报文序号还是u+1。
服务器等待客户机给自己发送确认收到的报文(LAST-ACK)。 第四次挥手: 客户机发送ACK=1,seq=u+1,ack=w+1,服务器随后进入TIME-WAIT状态。
服务器收到后进入CLOSED状态。等2MSL时间后客户机也进入CLOSED状态。
简言之:
客户机给服务器说我知道你可以断开了(ACK=1),我(客户机)发送的报文的序号是u+1,
你(服务器)下次给我(客户机)发送的报文序号是w+1。服务器收到客户机的确认后没啥可说的,就关闭连接了。
客户机等了2MSL后服务器没有动静了就也关闭连接了。

​ 3.三次握手和四次挥手也可以看成是小情侣谈恋爱的过程

​ 三次握手:表白在一起

​ 四次挥手:决裂要分手

二、UDP协议

​ 也称之为数据协议、不可靠协议

​ 早期的QQ使用的是纯生的(没有加任何额外的功能)UDP协议

​ 现在的QQ自己添加了很多技术和功能

​ 使用UDP的原因就是因为很简单 快捷 粗暴 只要指定对方的地址就可以发消息了

TCP我们可以看成是打电话:可靠的传输 TCP传输数据前需要三次握手建立连接

UDP我们可以看成是发短信:只要发了就行 不管对方看不看 不可靠传输 直接发送数据包 不关心对方是否接收成功

应用层

​ 应用层相当于是程序员自己写的应用程序 里面的协议非常的多

​ 常见的有:HTTP、HTTPS、FTP

socket模块

​ 如果我们需要编写基于网络进行数据交互的程序 意味着我们需要自己通过代码来控制我们之前所学习的OSI七层(很繁琐 很复杂 类似于我们自己编写操作系统)

​ socket也叫套接字 套接字就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象 完成两个应用程序之间的数据传输

​ AF_UNIX 基于文件类型的套接字家族(单机)

​ AF_INET 基于网络类型的接字家族(联网)

socket代码简介

import socket

# 1.产生一个socket对象并指定采用的通信版本和协议(TCP)
server = socket.socket() # 括号内不写参数 默认就是TCP协议 famliy=AF_INET基于网络的套接字 type=SOCK_STREAM流式协议即TCP
# 2.绑定一个固定的地址(服务端必备的条)
server.bind(('127.0.0.1', 8080)) # 127.0.0.1为本地回环地址 只有自己的电脑可以访问
# 3.设立半连接池
server.listen(5)
# 4.等待接客
sock, addr = server.accept() # return sock, addr 三次握手
print(sock, addr) # sock就是双向通道 addr就是客户端地址
# 5.服务客人
data = sock.recv(1024) # 接收客户端发送过来的消息 1024字节
print(data.decode('utf8'))
sock.send('客人您好 欢迎光临呀~'.encode('utf8')) # 给客户端发送消息 且消息必须是bytes类型
# 6.关闭双向通道
sock.close() # 四次挥手
# 7.关闭服务端
server.close() # 关店了 倒闭了 import socket # 1.生成socket对象指定类型和协议
client = socket.socket()
# 2.通过服务段的地址链接服务端
client.connect(('127.0.0.1', 8080))
# 3.直接给服务端发送消息
client.send('小二 上菜 把你家最好的的呈上来'.encode('utf8'))
# 4.接收服务端发送过来的消息
data = client.recv(1024)
print(data.decode('utf8'))
# 5.断开与服务端的链接
client.close()

代码优化

  1. 聊天的内容自定义

    针对消息采用input获取
  2. 让聊天循环起来

    将聊天的部分循环包起来
  3. 用户输入的消息不能为空

    本质其实是两边不能都是recv或者send 一定是一方收一方发
  4. 服务端多次重启可能会报错

    address already in use

    主要是mac电脑会报

    改端口号
#加入一条socket配置,重用ip和端口
import socket
from socket import SOL_SOCKET,SO_REUSEADDR
sk = socket.socket()
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字
sk.listen() #监听链接
conn,addr = sk.accept() #接受客户端链接
ret = conn.recv(1024) #接收客户端信息
print(ret) #打印客户端信息
conn.send(b'hi') #向客户端发送信息
conn.close() #关闭客户端套接字
sk.close() #关闭服务器套接字(可选)
  1. 当客户端异常断开的情况下 如何让服务端继续服务其他人客人

    windows服务端会直接报错

    msc服务端会有一段时间反复接收空消息延迟报错

    异常处理、空消息判断

客户端

import socket

client = socket.socket()
client.connect(('127.0.0.1', 8081))
while True:
msg = input('请输入您想要发送给服务端的消息>>>:').strip()
# 把发送的信息设置成自定义
if len(msg) == 0:
print('不能发送空消息')
continue
client.send(msg.encode('utf8'))
data = client.recv(1024)
print('来自于服务端发送过来的消息>>>:', data.decode('utf8'))

服务端

import socket
from socket import SOL_SOCKET, SO_REUSEADDR server = socket.socket()
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server.bind(('127.0.0.1', 8081))
server.listen(5) while True: # 链接循环
sock, addr = server.accept()
while True: # 通信循环
try:
# 当客户端输入为空的时候通过循环跳过后续代码,防止程序报错
data = sock.recv(1024)
if len(data) == 0:
break
print(f'来自于客户端{addr}的消息>>>:', data.decode('utf8'))
msg = input('请输入发送给客户端的消息(不能发空消息)>>>:').strip()
# 返回的信息设置成自定义
sock.send(msg.encode('utf8'))
except BaseException:
# 当客户端直接退出的时候服务端这边会报错,我们用异常处理让程序跳过这些会报错的代码,继续运行
break

半连接池的概念

server.listen(5)  #半连接池

当有多个客户端来链接的情况下 我们可以设置等待数量(不考虑并发问题)
假设服务端只有一个人的情况下 在测试半连接池的时候 可以不用input获取消息 直接把消息写死即可

TCP协议三握四挥、socket模块的更多相关文章

  1. 深入理解TCP三握四挥

    面试中被问到不少次TCP的三握四挥,今天特意来做一个总结(一些资料是很久前找的,忘了参考的链接了) 一.三次握手 首先来看一张图 最初,客户机A与服务器B的TCP进程都处于 CLOSED 状态. 然后 ...

  2. 详解TCP三握四挥

    TCP握手协议 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接.第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确 ...

  3. TCP实战一(三握四挥、流量控制)

    上一篇博文已经介绍了tcpdump的一些基本操作与命令,今天这篇博文将带你解密如何利用wireshark对tcpdump抓到的数据包进行可视化分析! 参考文献:https://zhuanlan.zhi ...

  4. 网络编程(二)--TCP协议、基于tcp协议的套接字socket

    一.TCP协议(Transmission Control Protocol 传输控制协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会 ...

  5. 网络编程(二)——TCP协议、基于tcp协议的套接字socket

    TCP协议与基于tcp协议的套接字socket 一.TCP协议(流式协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的 ...

  6. TCP 协议三次握手过程分析

    TCP 协议三次握手过程分析 TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: ...

  7. TCP协议三次握手

    TCP协议三次握手过程分析 TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: ...

  8. 网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

    TCP协议:传输协议,基于端口工作 三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立 ...

  9. TCP协议三次握手和四次挥手

    http://www.cnblogs.com/rootq/articles/1377355.html TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对 ...

  10. TCP协议三次握手与四次挥手通俗解析

    TCP/IP协议三次握手与四次握手流程解析 一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: 图1 TCP报文格式 上图中有几个字 ...

随机推荐

  1. 利用msg_msg实现任意地址读写

    利用msg_msg实现任意地址读写 msgsnd和msgrcv的源码分析 内核通过msgsnd和msgrcv来进行IPC通信.内核消息分为两个部分,一个是消息头msg_msg(0x30),以及后面跟着 ...

  2. mapboxgl加载tiff

    缘起 近期在项目中遇到这么一个需求,需要在地图上展示一组格网数据,格网大小为2m*2m,地图api用的mapboxgl.起初拿到这个需要感觉很easy,在地图上添加一个fill图层就好啦.把格网面数据 ...

  3. Jupyter Notebook单元格加宽的方法3种

    Jupyter Notebook的代码单元格比较窄,在我的屏幕上只占了一半都不到,网络搜索下,共找到3种加宽的方法,总结一下. (一)只改变当前Jupyter笔记本的单元格宽度 在Jupyter No ...

  4. 关于AWS-EC2或者多个资源的tag的批量添加-基于Resource Groups & Tag Editor 和 命令处理

    今天收到一个请求,需要对公司所有的ec2-添加上两个成本IO标签,因为机器太多了 想到了如下两种方案去批量处理 方案一:利用aws的 [Management Tools]下的 Resource Gro ...

  5. P3629 [APIO2010] 巡逻 (树的直径)

    (这道题考察了求直径的两种方法......) 在原图中,每条边要经过两次,增加1条后,形成了一个环,那么环上的边只需要经过一次了(大量画图分析得),再增加一条又会形成一个环,如果这两个环有重叠,重叠部 ...

  6. Codeforces 1684 E. MEX vs DIFF

    题意 给你n个非负整数的数列a,你可以进行K次操作,每次操作可以将任意位置的数数更改成任意一个非负整数,求操作以后,DIFF(a)-MEX(a)的最小值:DIFF代表数组中数的种类.MEX代表数组中未 ...

  7. Windows10 + Eclipse C/C++开发环境配置极简教程

    下载安装Eclipse 访问下载Eclipse IDE for C/C++ Developers https://www.eclipse.org/downloads/packages/ 将下载下来的压 ...

  8. 两个行内元素在一起,会出现一定的间距,即使将border、padding、margin都设置为零也无济于事,那么怎么才能去除这些间距呢?

    首先这里的div设置为了行内块元素,span本身为行内元素,并且设置了* {padding: 0; margin: 0;},那怎么清除元素之间的空白缝隙呢?? (1)给元素加浮动 <!DOCTY ...

  9. Sublime Text4(Build 4126) 安装备忘

    Sublime Text4(Build 4126) 安装备忘 sublime text 4126 PJ已测可用 打开浏览器进入网站https://hexed.it 打开sublime text4安装目 ...

  10. ThreadPoolExecutor BlockingQueue讲解

    有四种常用阻塞队列策略: 1.直接拒绝:(Direct Handoffs) 一个好的工作队列应该是不缓存任务,而是直接交给线程处理,就如SynchronousQueue一样.一个任务将会入队失败,如果 ...