1.UDP 通讯协议
UDP 的使用
服务端
- # import socket
- # s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- # s.bind(("127.0.0.1",1688))
- #
- # while True:
- # data,addr = s.recvfrom(1024)
- # s.sendto(data.upper(),addr)
- # print(data)
- # 客户端
- # import socket
- # c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- # addr = ("127.0.0.1",1688)
- #
- # while True:
- # msg = input(">>:")
- # c.sendto(msg.encode("utf-8"),addr)
- # data,addr = c.recvfrom(1024)
- # print(data,addr)
UDP 在使用时需要修改 socket 的参数 第一个仍是 AF_INET 第二个 SOCK_DGGRAM
不需要建立连接 所以没有三次握手 四次挥手
1. 修改 sock 的参数 / 2. 不需要监听和接收请求
相同点:
服务器: 都需要绑定 端口和 ip
recv 与 recvfrom 都是阻塞的
不同点:
服务器: 不需要监听 和接受请求
客户端: 不需要建立连接 直接发送即可
在 UDP 中 接收 recvfrom 发送 sendto
UDP 是基于数据报的协议, 发送和接收都是以数据报为单位
当接收放缓冲区的长度小于数据报的长度 Windows 会报异常 而 Linux 不会, 缓冲区有多大就接收多少
注意: UDP 在使用时 必须保证接收的缓冲区大小 大于或等于 发送报的大小
由于缓冲区大小不可能无限大, 所以 UDP 不适用数量较大的情空下 如果 一定使用 UDP 传输大量数据 需要自己对数据进行切割, 和组装
UDP 最大数据报 受数据帧大小限制 最大为 1427 字节
以下是计算方式:
1. 在链路层, 由以太网的物理特性决定了数据帧的长度为 64+18-1500+18, 其中的 18 是数据帧的头和尾, 也就是说数据帧的内容最大为 1500(不包括帧头和帧尾), 即 MTU(Maximum Transmission Unit)为 1500; 2. 在网络层, 因为 IP 包的首部要占用 20 字节, 所以这的 MTU 为 1500-20=1480; 3. 在传输层, 对于 UDP 包的首部要占用 8 字节, 所以这的 MTU 为 1480-8=1472;
所以, 在应用层, 你的 Data 最大长度为 1472. 当我们的 UDP 包中的数据多于 MTU(1472)时, 发送方的 IP 层需要分片 fragmentation 进行传输, 而在接收方 IP 层则需要进行数据报重组, 由于 UDP 是不可靠的传输协议, 如果分片丢失导致重组失败, 将导致 UDP 数据包被丢弃.
结论: 当数据量较大时 需要 TCP 进行分层传输
基于 UDP 的时间服务器
- # 服务端
- import socket
- import time
- s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- s.bind(("127.0.0.1",8888))
- ?
- while True:
- data,addr = s.recvfrom(1024)
- data = data.decode("utf-8")
- t = time.strftime(data,time.localtime())
- s.sendto(t.encode("utf-8"),addr)
- # 客户端
- import socket
- c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- c.sendto("%Y-%m-%d %H:%M:%S".encode("utf-8"),("127.0.0.1",8888))
- print(c.recvfrom(1024)[0])
UDP 的应用之 DNS
? 网络请求的具体流程
? 域名:
是给 IP 地址取的别名, 同时为了查询名字与地址对应关系是更快, 所以域名也划分了不同区域.? 分类
1.1 国际顶级域名: 工商企业 .com .top 网络提供商 .net 非营利组织 .org 教育 .edu?1.2 国际域名 中国 .cn 美国 .us 日本 .jp
但随之而来的问题是域名虽然简化了记忆, 但是数据传输依然要依赖 IP 地址和端口, 所以想要还要提供一个可以通过域名获取 ip 的机制, 这就是 DNS
DNS
全称域名解析服务器, 其本质上就是一个大型数据库系统
DNS 访问流程:
当我们要访问一个地址如 www.baidu.com 时
1. 浏览器首先会询问本地 DNS 服务器(即网络运营商如电信, 联通), 以获取对应的 IP,
2. 如果本地 DNS 中没有想要的记录, 则本地 DNS, 会询问根 (1 级) 域名服务器, 全球有 13 台
根域名服务器中不可能存储全世界所有 IP 所以它仅存储顶级 (2 级) 域名服务器的 IP
例如: COM 域主服务器的 IP.NET 域主服务器的 IP
3. 于是本地 DNS 得到 COM 域服务器 IP 后向其发送请求,
4. 由于一个域名可以对应多个 IP 所以还需要向三级域名主机发出请求
5. 最后将返回的 IP 信息缓存到本地 DNS 中备用
DNS 的问题
这样一来就造成一个问题 当一个已存在的域名更换 IP 后在一段时间内是无法访问的, 因为子域名服务器需要到达指定时间后才会自动刷新纪录
6. 目前的问题
TCP 中只能处理一个客户端的数据
UDP 虽然看起来可以同时处理, 但本质上也是按照顺序来处理的
为了提高用户访问速度, 必需找到一种可以使得服务器可以同时处理多个客户端请求的能力
这就需要使用并发编程了
来源: http://www.bubuko.com/infodetail-2975893.html