传输层之TCP与UDP协议
应用层
socket模块
socket代码简介
代码优化处理
半连接池的概念
传输层之TCP与UDP协议
1.TCP与UDP协议
规定了数据传输所遵循的规则
数据传输能够遵循的协议有很多,TCP和UDP是常见的两个
2.TCP协议
TCP协议
'''
基于TCP传输数据非常的安全,因为有双向通道
基于TCP传输数据,数据不容易丢失,不容易丢失的原因在于二次确认
每次发送数据都需要返回确认消息,否则在一定的时间会反复发送
'''
3.TCP协议--三次握手
P传输数据,数据不容易丢失,不容易丢失的原因在于二次确认
'''三次握手:'''
所谓三次握手,是指建立一个TCP连接时,需要客户端和服务器总共发送3个包
是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手。
建立双向通道,数据基于这个通道来回发送
'''洪水攻击:'''
同时让大量的客户端朝服务端发送建立TCP连接的请求
'''三次握手过程'''
(1)客户端向服务器端发送连接请求包SYN(syn=j),等待服务器回应;
(2)服务器端收到客户端连接请求包SYN(syn=j)后,将客户端的请求包SYN(syn=j)放入到自己的未连接队列,此时服务器需要发送两个包给客户端;
(3)客户端收到服务器的ACK(ack=j+1)和SYN(syn=k)包后,知道了服务器同意建立连接,此时需要发送连接已建立的消息给服务器;
向服务器发送连接建立的确认包ACK(ack=k+1),回应服务器的SYN(syn=k)告诉服务器,我们之间已经建立了连接,可以进行数据通信。
ACK(ack=k+1)包发送完毕,服务器收到后,此时服务器与客户端进入ESTABLISHED状态,开始进行数据传送。
4.TCP协议--四次挥手
'''四次握手特点:'''
断开双向通道,中间的俩步是不能合并的需要有检查的时间
'''四次握手过程 '''
(1)当服务端或者客户端不想再与对方进行通信之后,双方任意一方都可以主动发起断开链接的请求,我们还
是以客户端主动发起为例
(2)客户端由于已经没有任何需要发送给服务端的消息了,所以发起断开客户端到服务端的通道请求
(3)服务端收到该请求后同意了 至此客户端到服务端的单项通道断开
(4)服务端这个时候不会立刻朝客户端发器请求说那我也断开到你家的通道吧,同时它也不能拒绝人家断开的请求,服务端会去查看自己还有没有需要给客户端发送的数据,如果还有的话,就不会立马断开,先把数据发完才能断
(5)等服务端检查完毕之后也没有数据要发送给客户端了,这个时候就会朝客户端发起断开服务端到客户端的
通道请求
(6)客户端确认该请求,至此四次挥手完成
(7)挥手必须是四次,'中间的两次不能合并成一次,原因就在于需要检查是否还有数据需要给对方发送'
为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送;
但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;
但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
5.UDP协议
UDP协议
'''
TCP类似于打电话:你一句我一句
UDP类似于发短信:反正我发了,你看不看回不回复没关系
'''
UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。
UDP在传输数据报前不用在客户和服务器之间建立一个连接,没有任何的通道也没有任何的限制
UDP发送数据没有TCP安全,很随意
例如:QQ就是采用的就是UDP
6.TCP协议 vs UDP协议
TCP和UDP的主要区别:
TCP传输数据稳定可靠,适用于对网络通讯质量要求较高的场景,需要准确无误的传输给对方,
比如,传输文件,发送邮件,浏览网页等等
UDP的优点是速度快,但是可能产生丢包,所以适用于对实时性要求较高但是对少量丢包并没有太大要求的场景。
应用层
主要取决于程序员自己采用什么策略和协议
常见协议:HTTP、HTTPS、FTP.....
socket套接字编程
如果我们需要编写基于网络进行数据交互的程序 意味着我们需要自己通过代码来控制我们之前所学习的OSI七层(很繁琐 很复杂 类似于我们自己编写操作系统)
socket类似于操作系统 封装了丑陋复杂的接口提供简单快捷的接口
socket也叫套接字
基于文件类型的套接字家族(单机)
AF_UNIX
基于网络类型的套接字家族(联网)
AF_INET
1.两个程序之间的交互(简易版)
'''服务端'''
import socket
# 1.创建一个socket对象
server = socket.socket() # 括号内什么都不写 默认就是基于网络的TCP套接字
# 2.绑定一个固定的地址(ip\port)
server.bind(('127.0.0.1', 8080))
# 3.半连接层
server.listen(5)
# 4.开业,等待接客
sock, address = server.accept()
print(sock, address)
# 5.数据交互
sock.send(b'welcome to shanxi~')
data = sock.recv(1024) # 接收客户端发送的数据 1024bytes
print(data)
# 6.断开连接
sock.close() # 断连接
server.close() # 关机
'''客户端'''
import socket
# 1.创建一个socket对象
client = socket.socket() # 括号内什么都不写 默认就是基于网络的TCP套接字
# 2.连接服务端
client.connect(('127.0.0.1', 8080))
# 3.数据交互
data = client.recv(1024)
print(data)
client.send(b'so beautiful!!!')
# 6.断开连接
client.close() # 断连接
client.close() # 关机
2.两个程序之间的交互(优化版)
1.send与recv
客户端与服务端不能同时执行同一个
有一个收 另外一个就是发
有一个发 另外一个就是收
不能同时收或者发!!!
2.消息自定义
input获取用户数据即可(主要编码解码)
3.循环通信
给数据交互环节添加循环即可
4.服务端能够持续提供服务
不会因为客户端断开连接而报错
异常捕获 一旦客户端断开连接 服务端结束通信循环 调到连接处等待
5.消息不能为空
判断是否为空 如果是则重新输入(主要针对客户端)
6.服务端频繁重启可能会报端口被占用的错(主要针对mac电脑)
from socket import SOL_SOCKET,SO_REUSEADDR
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
7.客户端异常退出会发送空消息(针对mac linux)
针对接收的消息加判断处理即可
import socket
# 1.创建一个socket对象
server = socket.socket() # 括号内什么都不写 默认就是基于网络的TCP套接字
# 2.绑定一个固定的地址(ip\port)
server.bind(('127.0.0.1', 8080))
# 3.半连接层
server.listen(5)
# 4.开业,等待接客
sock, address = server.accept()
print(sock, address)
# 5.数据交互
while True:
try:
msg = input('请输入要发送给客户端的信息>>>:').strip()
sock.send(msg.encode('utf8'))
data = sock.recv(1024) # 接收客户端发送的数据 1024bytes
print(data.decode('utf8'))
except ConnectionError:
sock.close()
break
import socket
# 1.创建一个socket对象
client = socket.socket() # 括号内什么都不写 默认就是基于网络的TCP套接字
# 2.连接服务端
client.connect(('127.0.0.1', 8080))
# 3.数据交互
while True:
data = client.recv(1024)
print(data.decode('utf8'))
msg = input('请输入要发送给服务端的信息>>>:').strip()
if len(msg) == 0: continue
client.send(msg.encode('utf8'))
半连接层
当服务器在响应了客户端的第一次请求后会进入等待状态,会等客户端发送的ack信息,这时候这个连接就称之为半连接
半连接池其实就是一个容器,系统会自动将半连接放入这个容器中,可以避免半连接过多而保证资源耗光
产生半连接池的俩种情况:
客户端无法返回ACK信息
服务器来不及处理客户端的连接请求
设置的最大等待人数 >>>: 节省资源 提高效率
server.listen(5) 指定5个等待席位
主要是为了做缓冲 避免太多无效等待
标签:UDP,socket,编程,网络,TCP,连接,服务端,客户端
From: https://www.cnblogs.com/wwssadadbaba/p/16897668.html