udp的若干问题
时间:2022-06-05
本文章向大家介绍udp的若干问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
内部分享精简版
参考链接:https://blog.csdn.net/dog250/article/details/6896949
UDP SOCKET-SERVER
# encoding: utf-8
"""
@version: 1.0
@author: pierrexiong
@file: udp_server
@time: 2018/8/2 下午7:56
"""
from socket import *
HOST = '127.0.0.1'
PORT = 1080
s = socket(AF_INET, SOCK_DGRAM)
s.bind((HOST, PORT))
print '...waiting for message..'
while True:
data, address = s.recvfrom(1024)
print data, address
s.sendto('this is the UDP server', address)
套接字通信域
域 |
描述 |
---|---|
AF_INET |
ipv4 |
AF_INET6 |
ipv6 |
AF_UNIX |
unix域 |
AF_UPSPEC |
未指定 |
套接字类型
类型 |
描述 |
---|---|
SOCK_DGRAM |
固定长度的、无连接的、不可靠的报文传递(如UDP) |
SOCK_RAW |
IP协议的数据报接口(如ICMP) |
SOCK_SEQPACKET |
固定长度的、有序的、可靠的、面向连接的报文传递 |
SOCK_STREAM |
有序的、可靠的、双向的、面向连接的字节流(如TCP) |
UDP client
# encoding: utf-8
"""
@version: 1.0
@author: pierrexiong
@file: udp_test2
@time: 2018/7/30 下午12:21
"""
from socket import *
table_list = "test,test2,test3"
HOST = "127.0.0.1"
PORT = 1080
s = socket(AF_INET, SOCK_DGRAM)
for table in table_list.split(","):
message = str(table) + "|test_sendton"
print s.sendto(message, (HOST, PORT))
print "[send_message]:" + message
使用nc
nc -u 127.0.0.1 1080
linux设备块
echo "124" >> /dev/udp/127.0.0.1/1080
UDP的连接问题
发现问题
# encoding: utf-8
"""
@version: 1.0
@author: pierrexiong
@file: udp_test
@time: 2018/7/30 下午12:21
"""
from socket import *
table_list = "test,test2,test3"
HOST = "127.0.0.1"
PORT = 1081
s = socket(AF_INET, SOCK_DGRAM)
s.connect((HOST, PORT))
for table in table_list.split(","):
message = str(table) + "|test_sendalln"
print s.sendall(message)
print "[send_message]:" + message
s.close()
报错: connection refused
UDP是无连接的协议,为什么会出现connection refused的情况!!!
宏观解释
UDP协议是无连接的,但是UDP socket是可以连接的,且连接是单向的、不可靠的。
- 程序里对udp socket进行connect后,使用send(sendall)发送数据。
- 内核在应用connect之后就永久维护了这次UDP的连接,以后每次收发数据,内核不再需要分配/删除这些数据,而只是查找就可以了,同时也减少了数据的拷贝量
- 数据如果最终由IP封装(或者被任何有错误提示的下层协议封装),数据在半路上或者终点遇到某种问题不能到达目的地时,会有ICMP(对于非IP协议,可以是其它机制)错误信息返回。
- 对于有“连接”的UDP通信,由于内核协议栈已经维护了从源到目的地的单向连接,因此当错误信息发来的时候,内核协议栈会准确定位到该转发给哪个应用。
- 最后说明一点,UDP的连接是单向的,在调用connect的时候并不会产生任何通信流量,它只是在内核协议栈中绑定了一对五元组而已,该五元组是:UDP协议/源IP/源端口/目的IP/目的端口。
linux内核实际的处理逻辑
- 一个udp报文netfilter处理后,调用ip_local_deliver_finish,它根据ip头中的协议类型(TCP/UDP/ICMP/……),调用不同的4层接口函数进行处理。
- 对于udp而言,handler 是udp_rcv,它直接调用了__udp4_lib_rcv,查找相应的sock。如果sk不存在就回复icmp destination unreachable。
- 端口不可达报文(icmp)进入ip_local_deliver_finish,它调用icmp_rcv函数,进行处理。(其实这也是当初我认为客户端udp不会对端口不可达数据进行相应的原因,因为udp处理流程是udp_rcv)
- icmp_rcv函数调用了:icmp_pointersicmph->type.handler(skb); ipprot->err_handler,最终调用了__udp4_lib_err,可以将错误信息回传给应用程序。(前提是inet->recverr非0 或者 sk_state处于TCP_ESTABLISHED状态)
参考文章: https://blog.csdn.net/mrpre/article/details/43451775
udp高效率的神话
UDP高效的理由:
- UDP协议是无连接的,没有流控,没有握手,相比TCP确实少很多消耗。
- UDP不需要处理确认,没有回包。
UDP像短信, TCP像打电话. 发布垃圾广告的话, 短信可是快多了。
神化的打破:
- 复杂网络下,UDP丢包严重,需要在上层应用做大量的逻辑。
- UDP包是固定长度的,会造成一定的资源浪费。
- (UDP可能每次发送的包是MTU的几百分之一,也可能是MTU的几百倍.前者太低效,后者将消耗转嫁给了IP。)
- TCP在复杂情况下有更多的算法来对传输层进行调优。
UDP的丢包问题
UDP丢包产生的原因:
- 超过发送端的缓冲
- 网络层及以下层面的数据丢失
- UDP Server处理能力不够大包丢包概率更高:
- UDP本身不会重传数据包,无法重组数据报。
- 单个MTU包丢失会导致整个UDP包的数据丢失。
- (数据中心内部,错误丢包率在十万分之一(1e-5))
UDP的使用场景
网络质量:
- 相对在网络极度拥堵的情况下,udp的丢包率极其高。需要在上层实现重传、拥塞控制等。(TCP in UDP)
- 通讯的持续性和交互性:
- 短连接通信:例如DNS查询。
- 长连接:TCP握手和挥手的额外时间会平摊到持久的通信中。
- UDP协议的通信完全取决于应用程序本身的发送和接收、TCP协议的通信则要受到协议栈的影响通讯行为
- 多点通讯:
- TCP不适合多点通讯(握手和挥手协议决定)
- 数据边界:
- 每个UDP包都是有边界的、而TCP需要按照数据本身来界定边界
UDP的一些知名应用
- DNS
- DHCP
- OpenSSL
- OpenV**
- QUIC
- KCP
QUIC简要介绍
QUIC全称quic udp internet connection,是Google发明并于2013年部署使用的传输协议。狭隘的讲,QUIC就等于用UDP实现的HTTP2 + TLS + TCP。
Chrome等主流应用均已经支持QUIC。
image.png
- 使用密码记录工具keepass来保存密码
- 机器人带着VR学习,最后学会了人工智能
- 超经典的JBOSS入门文章
- ASP.NET2.0应用中定制安全凭证
- AI造的AI,比人造的还厉害,该喜还是该忧?
- Mono 3.2 测试NPinyin 中文转换拼音代码
- Reactive Extensions介绍
- Reactive Extensions(Rx) 学习
- 发布一个日期选择控件(ASPNET2.0)
- 做程序员压力山大,很多人都快疯了
- 小程序让交通出行变得如此简化,看看这些微信小程序你有在用了吗?
- 中小企业如何选择DDoS防御方案?
- “熊医生”出诊正确率超九成 医院:人工智能更多是辅助
- PLC编程优化方法,让程序运行提速!
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法