DPDK用户态协议栈-Tcp Posix API 1
和udp一样,我们需要实现和系统调用一样的接口来实现我们的tcp server
。先来看看我们之前写的unix_tcp使用了哪些接口,这边我加上两个系统调用,分别是接收数据和发送数据。
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>int main(int argc, char* argv) {int sock = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in servaddr;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_family = AF_INET;servaddr.sin_port = htons(9999);bind(sock, (struct sockaddr*)&servaddr, sizeof(struct sockaddr));listen(sock, 10);struct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);char buffer[64] = {0};int fd = accept(sock, (struct sockaddr*)&clientaddr, &len);while (1) {int nb_recv = recv(fd, buffer, 64, 0);if (nb_recv > 0) {printf("tcp recv : %s\n", buffer);send(fd, buffer, nb_recv, 0);memset(buffer, 0, 64);}}return 0;
}
- socket
- bind
- listen
- accept
- recv
- send
tcp的posix实现
bitmap
static struct localhost* get_host_fromfd(int sockfd) {struct localhost* htp = get_lhost_instance();struct localhost* host;for(host = htp; host != NULL; host = host->next) {if (host->fd == sockfd) {return host;}}struct ln_tcp_stream* stream;struct ln_tcp_table* table = get_tcp_table_instance();for(stream = table->streams; stream != NULL; stream = stream->next) {if (stream->fd == sockfd) {return stream;}}return NULL;
}
根据sockfd来搜索对应的控制块(tcp和udp同一个函数)。在之前的udp api实现的过程中实现了一个伪bitmap(后续会完善的)。现在加上了tcp,在函数中加上tcp控制块相关的遍历条件。
tcp server的最后两个状态
static int ln_tcp_handle_close_wait(struct ln_tcp_stream* stream, struct rte_tcp_hdr* tcphdr) {if (tcphdr->tcp_flags & RTE_TCP_FIN_FLAG) {if (stream->status == LN_TCP_STATUS_CLOSE_WAIT) {//}}return 0;
}static int ln_tcp_handle_last_ack(struct ln_tcp_stream* stream, struct rte_tcp_hdr* tcphdr) {if (tcphdr->tcp_flags & RTE_TCP_ACK_FLAG) {if (stream->status == LN_TCP_STATUS_LAST_ACK) {stream->status = LN_TCP_STATUS_CLOSED;struct ln_tcp_table* table = get_tcp_table_instance();LL_REMOVE(stream, table->streams);table->count--;rte_ring_free(stream->recvbuf);rte_ring_free(stream->sendbuf);rte_free(stream);}}return 0;
}
修改一些之前的API
由于tcp和udp都有创建套接字,绑定等通用的部分,所以我们要在之前写的api上做一些增加和修改,让TCP和UDP都可以使用他们。
socket创建套接字
static struct localhost* get_host_fromip_port(uint32_t ip, uint16_t port, uint8_t proto) {struct localhost* htp = get_lhost_instance();struct localhost* host;for(host = htp; host != NULL; host = host->next) {if (host->localip == ip && host->localport == port && host->protocol == proto) {return host;}}return NULL;
}int nsocket(__attribute__((unused)) int domain, int type, __attribute__((unused)) int protocol) {int fd = get_fd_frombitmap();if (type == SOCK_DGRAM) {struct localhost* host = rte_malloc("localhost", sizeof(struct localhost), 0);if (host == NULL) {return -1;}memset(host, 0, sizeof(struct localhost));host->fd = fd;if (type == SOCK_DGRAM) {host->protocol = IPPROTO_UDP;}host->recvbuf = rte_ring_create("recv buf", RING_SIZE, rte_socket_id(), RING_F_SC_DEQ | RING_F_SP_ENQ);if (host->recvbuf == NULL) {rte_free(host);return -1;}host->sendbuf = rte_ring_create("send buf", RING_SIZE, rte_socket_id(), RING_F_SC_DEQ | RING_F_SP_ENQ);if (host->sendbuf == NULL) {rte_ring_free(host->recvbuf);rte_free(host);return -1;}pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;rte_memcpy(&host->mutex, &blank_mutex, sizeof(pthread_mutex_t));rte_memcpy(&host->cond, &blank_cond, sizeof(pthread_cond_t));struct localhost* lhp = get_lhost_instance();LL_ADD(host, lhp);}else if (type == SOCK_STREAM) {struct ln_tcp_stream* stream = rte_malloc("ln_tcp_stream", sizeof(struct ln_tcp_stream), 0);if (stream == NULL) {return -1;}stream->fd = fd;stream->proto = IPPROTO_TCP;stream->next = stream->prev = NULL;stream->recvbuf = rte_ring_create("tcp recv buf", RING_SIZE, rte_socket_id(), RING_F_SC_DEQ | RING_F_SP_ENQ);if (stream->recvbuf == NULL) {rte_free(stream);return -1;}stream->sendbuf = rte_ring_create("tcp send buf", RING_SIZE, rte_socket_id(), RING_F_SC_DEQ | RING_F_SP_ENQ);if (stream->sendbuf == NULL) {rte_ring_free(stream->sendbuf);rte_free(stream);return -1;}pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;rte_memcpy(&stream->cond, &blank_cond, sizeof(pthread_cond_t));rte_memcpy(&stream->mutex, &blank_mutex, sizeof(pthread_mutex_t));struct ln_tcp_table* table - get_tcp_table_instance();LL_ADD(stream, table->streams);table->count++;}return fd;
}
bind绑定
int nbind(int sockfd, const struct sockaddr *addr, __attribute__((unused)) socklen_t addrlen) {void* hostinfo = get_host_fromfd(sockfd);if (hostinfo == NULL) {return -1;}struct localhost* host = (struct localhost*)hostinfo;if (host->protocol == IPPROTO_UDP) {if (host == NULL) {return -1;}const struct sockaddr_in* laddr = (const struct sockaddr_in*)addr;host->localport = laddr->sin_port;rte_memcpy(&host->localip, &laddr->sin_addr.s_addr, sizeof(uint32_t));rte_memcpy(host->localmac, nSrcMac, RTE_ETHER_ADDR_LEN);}else {struct ln_tcp_stream* stream = (struct ln_tcp_stream*)hostinfo;const struct sockaddr_in* laddr = (const struct sockaddr_in*)addr;stream->dport = laddr->sin_port;rte_memcpy(&stream->dip, &laddr->sin_addr.s_addr, sizeof(uint32_t));rte_memcpy(&stream->localmac, nSrcMac, RTE_ETHER_ADDR_LEN);stream->status = LN_TCP_STATUS_CLOSED;}return 0;
}
close
int nclose(int fd) {void* hostinfo = get_host_fromfd(fd);if (hostinfo == NULL) {return -1;}struct localhost* host = (struct localhost*)hostinfo;if (host->protocol == IPPROTO_UDP) {struct localhost* lhp = get_lhost_instance();LL_REMOVE(host, lhp);if (host->recvbuf) {rte_ring_free(host->recvbuf);}if (host->sendbuf) {rte_ring_free(host->sendbuf);}rte_free(host);set_fd_frombitmap(fd);}else if (host->protocol == IPPROTO_TCP){struct ln_tcp_stream* stream = (struct ln_tcp_stream*)hostinfo;if (stream->status != LN_TCP_STATUS_LISTEN) {struct ln_tcp_fragment* fragment = rte_malloc("close frag", sizeof(struct ln_tcp_fragment), 0);if (fragment == NULL) {return -1;}memset(fragment, 0, sizeof(struct ln_tcp_stream));fragment->sport = stream->dport;fragment->dport = stream->sport;fragment->acknum = stream->recv_next;fragment->seqnum = stream->recv_next;fragment->windows = LN_TCP_INITIAL_WINDOWS;fragment->hdr_off = 0x50;fragment->tcp_flags = RTE_TCP_FIN_FLAG | RTE_TCP_ACK_FLAG;rte_ring_mp_enqueue(stream->sendbuf, (void*)fragment);stream->status = LN_TCP_STATUS_LAST_ACK;set_fd_frombitmap(fd);}else {struct ln_tcp_table* tb = get_tcp_table_instance();LL_REMOVE(stream, tb->streams);rte_free(stream);}}return 0;
}
tcp的专有API
listen监听
int nlisten(int sockfd, __attribute__((unused))int backlog) {void* hostinfo = get_host_fromfd(sockfd);if (hostinfo == NULL) {return -1;}struct ln_tcp_stream* stream = (struct ln_tcp_stream*)hostinfo;if (stream->proto == IPPROTO_TCP) {stream->status = LN_TCP_STATUS_LISTEN;}return 0;
}
accept建立连接
int naccept(int sockfd, struct sockaddr *addr, __attribute__((unused))socklen_t *addrlen) {void* hostinfo = get_host_fromfd(sockfd);if (hostinfo == NULL) {return -1;}struct ln_tcp_stream* stream = (struct ln_tcp_stream*)hostinfo;if (stream->proto == IPPROTO_TCP) {struct ln_tcp_stream* apt = NULL;pthread_mutex_lock(&stream->mutex);while ((apt = ln_get_accept_stream(stream->dport)) == NULL) {pthread_cond_wait(&stream->cond, &stream->mutex);}pthread_mutex_unlock(&stream->mutex);struct sockaddr_in* addri = (struct sockaddr_in*)addr;addri->sin_port = apt->sport;rte_memcpy(&addri->sin_addr.s_addr, &apt->sip, sizeof(uint32_t));return apt->fd;}return -1;
}
参考资料:https://github.com/0voice
相关文章:
DPDK用户态协议栈-Tcp Posix API 1
和udp一样,我们需要实现和系统调用一样的接口来实现我们的tcp server。先来看看我们之前写的unix_tcp使用了哪些接口,这边我加上两个系统调用,分别是接收数据和发送数据。 #include <stdio.h> #include <arpa/inet.h> #include …...
【人工智能-科普】图神经网络(GNN):与传统神经网络的区别与优势
文章目录 图神经网络(GNN):与传统神经网络的区别与优势什么是图神经网络?图的基本概念GNN的工作原理GNN与传统神经网络的不同1. 数据结构的不同2. 信息传递方式的不同3. 模型的可扩展性4. 局部与全局信息的结合GNN的应用领域总结图神经网络(GNN):与传统神经网络的区别与…...
LabVIEW实现UDP通信
目录 1、UDP通信原理 2、硬件环境部署 3、云端环境部署 4、UDP通信函数 5、程序架构 6、前面板设计 7、程序框图设计 8、测试验证 本专栏以LabVIEW为开发平台,讲解物联网通信组网原理与开发方法,覆盖RS232、TCP、MQTT、蓝牙、Wi-Fi、NB-IoT等协议。 结合实际案例,展示如何利…...
[pdf,epub]228页《分析模式》漫谈合集01-45提供下载
《分析模式》漫谈合集01-45的pdf、epub文件提供下载。已上传至本号的CSDN资源。 如果CSDN资源下载有问题,可到umlchina.com/url/ap.html。 已排版成适合手机阅读,pdf的排版更好一些。 ★UMLChina为什么叒要翻译《分析模式》? ★[缝合故事]…...
Kafka的消费消息是如何传递的?
大家好,我是锋哥。今天分享关于【Kafka的消费消息是如何传递的?】面试题。希望对大家有帮助; Kafka的消费消息是如何传递的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Kafka中,消息的消费是通过消费…...
二分查找(Java实现)(1)
二分查找(Java实现)(1) leetcode 34.排序数组中查找元素第一个和最后一个位置 题目描述: 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如…...
力扣103.二叉树的锯齿形层序遍历
题目描述 题目链接103. 二叉树的锯齿形层序遍历 给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 示例 1ÿ…...
Search with Orama
1.前言 在不久之前,我把 DevNow 的搜索组件通过 Lunr 进行了重构,从前端角度实现了对文章内容的搜索,但是在使用体验上,感觉不是特别好,大概有如下几个原因: 社区的文章数量比较少,项目的 Com…...
一万台服务器用saltstack还是ansible?
一万台服务器用saltstack还是ansible? 选择使用 SaltStack 还是 Ansible 来管理一万台服务器,取决于几个关键因素,如性能、扩展性、易用性、配置管理需求和团队的熟悉度。以下是两者的对比分析,帮助你做出决策: SaltStack&…...
计算机类大厂实习春招秋招开发算法面试问答练习题
计算机类大厂实习春招秋招开发算法面试问答练习题 下面有十个非常重要且常问,面试者却注意不到的问题,我们一个个来看,一个个来学。 线程创建到删除过程中,底层是怎么实现的 1.线程创建 线程创建是线程生命周期的起点。在操作系统中,线程可以通过多种方式创建,但无论哪…...
【热门主题】000068 筑牢网络安全防线:守护数字世界的坚实堡垒
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【热…...
RPC与HTTP调用模式的架构差异
RPC(Remote Procedure Call,远程过程调用)和 HTTP 调用是两种常见的通信模式,它们在架构上有以下一些主要差异: 协议层面 RPC:通常使用自定义的二进制协议,对数据进行高效的序列化和反序列化&am…...
计算机网络之传输层协议UDP
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 计算机网络之传输层协议UDP 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记,欢迎大家在评论区交流讨论💌 目…...
Uniapp 微信小程序内打开web网页
技术栈:Uniapp Vue3 简介 实际业务中有时候会需要在本微信小程序内打开web页面,这时候可以封装一个路由页面专门用于此场景。 在路由跳转的时候携带路由参数,拼接上web url,接收页面进行参数接收即可。 实现 webview页面 新…...
阅读方法论
选择固有缺陷,选项是对比出来的...
373. 查找和最小的 K 对数字
参考的这个博客: https://zhuanlan.zhihu.com/p/457239781 然后看这个代码我想到了另外一种方法,就是一步一步往里加元组 ( i , j ) (i,j) (i,j),看代码就知道了,不过需要做一步去重,去重不能用 i n t [ ] int[] int…...
常用函数的使用错题汇总
目录 new/delete malloc/free1. 语言和类型2. 内存分配3. 内存释放4. 安全性和类型安全5. 其他特性总结 线程停止文件流 new/delete malloc/free malloc/free 和 new/delete 是 C/C 中用于动态内存管理的两种方式,它们有一些重要的区别。以下是这两种方式的比较&…...
uniapp手机端一些坑记录
关于 z-paging-x 组件,在ios上有时候通过弹窗去粗发它reload时会触发闪退,可能是弹框插入进去导致的DOM 元素已经被移除或者不可用,解决办法是加上他自带属性 :showRefresherWhenReload"true" 加上showRefresherWhe…...
2024学习之前端微信小程序开发教程,从入门到精通-含基础+实战+源码code
目录 一、简单介绍 二、课程需知 三、内容编排 1、小程序基础 起步式 目录结构 小程序框架 场景值 逻辑层 视图层 组件 视图容器 基础内容 表单组件 导航 媒体组件 Api 路由 界面 交互 网络 数据缓存 自定义组件 2、项目实战 …...
netconf 代码架构
NETCONF(Network Configuration Protocol)是一种基于 XML 的网络配置管理协议,主要用于在网络设备之间进行配置管理、状态监控和操作。它被设计为一种可扩展的协议,并且在自动化网络管理中扮演着重要角色。NETCONF 通过安全的通信…...
蒙特卡洛方法(Monte Carlo,MC)
目录 1 序言 2 Monte Carlo法计算积分 3 最优化计算Monte Carlo法 1 序言 蒙特卡罗方法(Monte Carlo)是由冯诺依曼和乌拉姆等人发明的,“蒙特卡罗”这个名字是出自摩纳哥的蒙特卡罗赌场,这个方法是一类基于概率的方法的统称。是一种应用随机数来进行…...
python学习笔记8-函数2
参数传递 传不可变对象 & 传可变对象 def func(b):print(id(a), a) #140737041872600 234print(id(b), b) #140737041872600 234a 234 func(a)def func(b):print(id(a), a) #1413554098560 [343]print(id(b), b) #1413554098560 [343]a [343] func(a)def func(b):b.appe…...
电商项目高级篇06-缓存
电商项目高级篇06-缓存 1、docker下启动redis2、项目整合redis3、redis改造三级分类业务 缓存 流程图: data cache.load(id);//从缓存加载数据 If(data null){ data db.load(id);//从数据库加载数据 cache.put(id,data);//保存到 cache 中 } return data;在我们…...
使用 `aircrack-ng`扫描、获取握手包
使用 aircrack-ng 工具集来扫描 5GHz WiFi 网络的过程与扫描 2.4GHz 网络类似,但需要注意一些特定的配置和命令。以下是一个详细的步骤指南,帮助你在 5GHz 频段上扫描 WiFi 网络并捕获握手包。 ### 前提条件 1. **操作系统**:通常在 Linux 系…...
基于大数据python 酒店数据分析可视化大屏系统(源码+LW+部署讲解+数据库+ppt)
!!!!!!!!! 很对人不知道选题怎么选 不清楚自己适合做哪块内容 都可以免费来问我 避免后期給自己答辩找麻烦 增加难度(部分学校只有一次答辩机会 没弄好就延迟…...
uniapp中父组件调用子组件方法
实现过程(setup语法糖形式下) 在子组件完成方法逻辑,并封装。在子组件中使用defineExpose暴露子组件的该方法。在父组件完成子组件ref的绑定。通过ref调用子组件暴露的方法。 子组件示例 <template> </template><script se…...
STL算法之set相关算法
STL一共提供了四种与set(集合)相关的算法,分别是并集(union)、交集(intersection)、差集(difference)、对称差集(symmetric difference)。 目录 set_union set_itersection set_difference set_symmetric_difference 所谓set,可细分为数学上定义的和…...
vscode中json文件的注释飘红
vscode的json文件 添加注释,提示json中不允许有注释,点编辑器最下面的json,如下图 然后选择如上图的json with comments就好了...
【微服务】SpringBoot 整合Redis Stack 构建本地向量数据库相似性查询
目录 一、前言 二、向量数据库介绍 2.1 什么是向量数据库 2.2 向量数据库特点 2.3 向量数据库使用场景 三、常用的向量数据库解决方案 3.1 Milvus 3.1.1 Milvus是什么 3.1.2 Milvus主要特点 3.2 Faiss 3.2.1 Faiss是什么 3.2.2 Faiss主要特点 3.3 Pinecone 3.3.1 …...
三:安装服务-controller node
一:工具、环境准备-controller node 二:OpenStack环境准备-controller node 三:安装服务-controller node 四:工具、环境准备-compute node 五:OpenStack环境准备-compute node 六:安装服务-compute node 七…...
做名片哪个网站最好/优化推广方案
本代码由广州75中麻玉国老师分享在NOI教练群内,自己亲测了一下,感觉蛮好玩,所以特意收藏下来,具体代码如下:import pdfplumberfrom openpyxl import Workbookwb Workbook() # 创建文件对象ws wb.active # 获取第一…...
汉阳网站建设鄂icp/厦门百度代理公司
📚 本项目为从零开始学 Web 前端系列图文教程。从零基础开始,手把手教你进入前端开发的世界。从入门到进阶,我们一同前行。 项目背景 大家好,我是前端队长Daotin,想要获取更多前端精彩内容,关注我(全网同…...
表白视频制作网站/长沙百度快速排名优化
简介 这节课NeHe课程主要向我们展示了将物理运动规律引入到三维场景中,模拟真实物体的位置变化过程。这节课分别模拟了如下几种运动方式: (1)在重力作用下的抛物线运动; (2)匀速运动 ÿ…...
360网站建设/西安seo培训
成为Excel精英真不容易啊,正则表达式必须拿下! ()可以让括号内作为一个整体产生重复Sub t29()Dim regx As New RegExpDim srsr "A3A3QA3A37BDFE87A8"With regx.Global True.Pattern "((A3){2})" 相当于A3A3Debug.Print .Replace(…...
泰安网站的建设/海口百度seo公司
1. 前言 说起 Github,大家可能都觉得那只是程序员的聚集地。今天就要告诉大家,Github 不仅仅是 Coder 们的专属,它同时也是一个巨大的资源宝库! 由于我也算是个半吊子的程序员了,所以用 Github 也算久的了࿰…...
东莞市南华职业技术学校/seo推广系统排名榜
如果您想向用户提供正在进行某些操作的可视反馈(并且可能会对进度提供一些提示),请转到JProgressBar和SwingWorker(more details)。另一方面,如果您想要有一种情况,当用户单击按钮并且任务应该在后台运行时(当用户执行其他操作时),…...