UDP socket查询高速缓存
UDP没有连接的概念,所以UDP不会保存 “正在和谁通信的信息” ,换句话说,UDP数据的发送是oneshot的。
我们来做个实验,两台机器分别部署UDP的server和client。
先看server:
#define PORT 2222
int main()
{int sockfd;char buffer[MAXLINE];char *tosend = "aaaaaaaaaaa";struct sockaddr_in servaddr, cliaddr;sockfd = socket(AF_INET, SOCK_DGRAM, 0);servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = inet_addr("192.168.56.101");servaddr.sin_port = htons(PORT);bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr));n = recvfrom(sockfd, (char *)buffer, 64, MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len);sendto(sockfd, (const char *)tosend, strlen(tosend), MSG_CONFIRM, (const struct sockaddr *) &cliaddr, len);return 0;
}
server逻辑很简单,接受client的一个buffer,然后回复一堆aaaaaaa…
再看client:
#define PORT 2222int main()
{int sockfd;char buffer[MAXLINE];char *tosend = "bbbbbbbbbbbbb";struct sockaddr_in servaddr;sockfd = socket(AF_INET, SOCK_DGRAM, 0);servaddr.sin_family = AF_INET;servaddr.sin_port = htons(PORT);servaddr.sin_addr.s_addr = inet_addr("192.168.56.101");sendto(sockfd, (const char *)tosend, strlen(tosend), MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr));n = recvfrom(sockfd, (char *)buffer, 64, MSG_WAITALL, (struct sockaddr *) &servaddr, &len);printf("data: %s %d\n", buffer, htons(servaddr.sin_port));return 0;
}
在client上配置iptables规则:
iptables -t raw -A INPUT -p udp -j NOTRAC
iptables -t nat -A INPUT -p udp --sport 2222 -j SNAT --to-source :12345
意思很简单,client给server的2222端口发送一堆b,然后server使用12345端口回复一堆a给client。作为iptables的替代,在recvfrom和sendto之间再次bind不同的address即可。
这肯定是可行的,数据是可以发送成功的。
- 两个UDP socket互相通信,源端口是可以不断变化的。
UDP接收端在真的收到数据报文之前,是不知道源端口变化了的,按照UDP的规范,UDP socket在协议栈里不能以4元组来组织,而只能通过 {本地IP地址,本地端口} 来组织。
即便是connected UDP也不行。
connected UDP在查找时只是在compare时附加了源IP地址和源端口的检测。
这意味着一些高负载流式的UDP服务(用UDP传输流式数据,比如quic)在 连接数 (即唯一四元组的数量)很多时,socket无法通过四元组很好地进行散列,而只能退化成一条链表:
- 服务端的端口与IP均相同。(相关的socket会hash到同一个bucket)
- 客户端的端口与IP无法被利用(按照UDP语义和规范,它们‘可能’会发生变化)。
但是,可以为四元组加个缓存!
我们看Linux内核的实现,为了优化查询性能,在 目标端口 hash之外,引入了一个 {目标IP,目标端口} 二元组hash,当端口hash表冲突链长度大于10时,启用二元组hash查询。
然而,无济于事!
为了解决这个问题,加个四元组hash表查询缓存是一个正确的思路。缓存是规范外的。
我们可以看到,类似nf_conntrack,UDP防火墙等等均采用了 “UDP四元组作为连接性” 来优化查询性能的。我们看一个nf_conntrack的例子:
ipv4 2 udp 17 22 src=192.168.56.101 dst=192.168.56.110 sport=2222 dport=45069 [UNREPLIED] src=192.168.56.110 dst=192.168.56.101 sport=45069 dport=12345 mark=0 zone=0 use=2
实现这个代码非常简单,照猫画虎UDP socket组织的hash2即可,在hash2操作的地方,按照引入一个四元组hash3的对应操作即可:
- udp_lib_get_port: 按照四元组插入hash3。
- __udp4_lib_lookup_skb: 先按照四元组查询hash3。
- udp_lib_rehash: 如果探测到元组变化,则更新hash3。
- udp_lib_unhash: 结束时,从hash3中摘除当前socket四元组item。
是不是很简单呢?当然,经理并不这么认为。
浙江温州皮鞋湿,下雨进水不会胖。
UDP socket查询高速缓存相关推荐
- 【转】Linux编程之UDP SOCKET全攻略
转自:http://www.cnblogs.com/skyfsm/p/6287787.html?utm_source=itdadao&utm_medium=referral 这篇文章将对lin ...
- 超详细的Linux编程之UDP SOCKET全攻略(一文让你彻底了解)
一.基本的udp socket编程 1. UDP编程框架 要使用UDP协议进行程序开发,我们必须首先得理解什么是什么是UDP?这里简单概括一下. UDP(user datagram protocol) ...
- Linux Kernel TCP/IP Stack — Socket Layer — TCP/UDP Socket 网络编程
目录 文章目录 目录 TCP/UDP Socket 逻辑架构 创建 Socket 绑定 Socket 请求建立 Socket 连接 监听 Socket 接受请求 关闭连接 数据的发送和接收 send ...
- LINUX下UDP实现消息镜像通信,linux环境下基于udp socket简单聊天通信
客户端代码:client.c /* * File: main.c * Author: guanyy * * Created on 20161202 * * 主要实现:客户端和服务端相互通信 */ #i ...
- 内核中的UDP socket流程(2)——API “sys_socket”
内核中的UDP socket流程(2)--API "sys_socket" 作者:gfree.wind@gmail.com 原文:http://blog.chinaunix.net ...
- TCP/UDP,SOCKET,HTTP,FTP协议简析
(一)TCP/UDP,SOCKET,HTTP,FTP简析 TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层: 网络层:IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议 传 ...
- UDP socket programming in php
2019独角兽企业重金招聘Python工程师标准>>> http://www.binarytides.com/udp-socket-programming-in-php/ UDP s ...
- UDP socket 设置为的非阻塞模式
UDP socket 设置为的非阻塞模式 Len = recvfrom(SocketFD, szRecvBuf, sizeof(szRecvBuf), MSG_DONTWAIT, (struct s ...
- linux系统udp通信程序,Linux UDP socket编程(UDP通讯模型) | C/C++程序员之家
Linux UDP socket编程(UDP通讯模型): UDPClient + UDPService. Linux下大多数网络程序都是基于TCP的,很少基于UDP,简单的通讯模型如下,开发时候备用! ...
- 内核中的UDP socket流程(1)
内核中的UDP socket流程(1) 相对于TCP,UDP协议要简单的多.所以我决定由简入繁,先从UDP协议入手. 前一遍文章已经确定了struct sk_buff被用于socket的接受和发送缓 ...
最新文章
- UNIX文件的实现——索引节点
- 数据去中心化的场景与流程
- 王道计算机考研 数据结构 (图-上)
- 注释和简单用户交互程序
- Oracle中一般游标与REF游标的区别
- Linux下后台执行java程序
- 我敲的不是代码,而是……
- [网络通信协议]websocket
- 动易cms .net版本后台拿shell
- 某程序员求助:简历造假,如今面试通过,要坦白吗?
- 黑客攻防专题九:菜鸟 Sa 注入=肉鸡
- java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled.
- Catagory添加属性、扩展方法
- SSD接口SATA/PCIE/mSATA/M.2分析
- Windows cmd 查看文件MD5 SHA1 SHA256
- windows 7下进入System帐号并运行桌面系统
- PWM调光线性恒流LED恒流芯片X10S
- 长尾效应解析以及长尾效应在电商中的应用
- windows开启远程桌面,防火墙拦截:只允许特定IP远程
- 一次正交设计和组合设计之旅