0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何让自己创建的tcp协议栈为其他应用程序提供网络服务?

FPGA之家 来源:embed linux share 作者:embed linux share 2021-03-22 11:07 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一般来说,使用套接字进行网络编程时,默认使用linux内核提供的网络服务。但是,现在我们自己在用户空间构建了一个tcp协议栈,并且让它为其他应用程序提供网络服务,这势必要求我们自己实现一套新的套接字接口,并且提供给其他应用程序指定使用。

但是,我们并不希望把该tcp协议栈封装成动态库的形式,因为这样一来,应用程序的编译是必须要把库一起连接进去的。那么原生网络编程开发的程序就不能基于我们tcp协议栈来运行了。

一种较好的设计思路是,把tcp协议栈剥离出来作为一个独立的组件来运行,然后通过一个中间件,把网络程序与tcp协议栈协同工作起来。这个中间件的主要工作就是负责偷龙换凤,也就是把网络程序中的内核网络服务转换成独立运行的tcp协议栈的网络服务。

核心思路:网络程序(curl)+自定义套接字库(liblevel.so)+tcp协议栈(level-ip),如下图:

curl小工具

curl是一种命令行工具,作用是发出网络请求,然后得到和提取数据,显示在"标准输出"(stdout)上面。我们直接在curl命令后加上网址和端口,就可以看到网页源码。比如抓取www.sina.com网址:

curl www.sina.com 80

下面我们来看一个curl工具的简易实现,如下图:

第3行:判断目标主机名是否合法

第11行:判断目标端口好是否合法

第16行:完成主机名到地址解析

第21行:使用socket申请一个套接字描述符

第23行:使用connect函数发起tcp连接

第30行:按照http 1.1协议来填充要发送的内容,此处为http协议的get请求

第33行:调用write来发送网络数据

第41行:在while循环中重复接收服务器返回来的网页数据,并且打印在当前控制台终端上。

这是标准的网络应用程序,使用gcc命令编译后即可运行。

gcc curl.c -o curl

liblevelip.so库

level-ip脚本

liblevelip.so库重新封装了常用的socket套接字,并借助socket原生的本地套接字接口来与tcp协议栈(level-ip)进行数据通信。以后在curl程序使用socket套接字时,优先使用该库的服务接口,而不是内核的网络服务。这是通过level-ip这个shell脚本完成的,具体命令如下:

./level-ip curl www.sina.com 80

我们来分析一下level-ip这个shell脚本的原理,如下图:

第1行:执行该shell脚本由/bin/sh程序来执行。

第3行:指定脚本如果发生错误,或者遇到不存在的变量就报错,并停止执行。

第5行:保存脚本的第一个参数到prog变量中。

第6行:去掉一个参数,即原来的1,2,依此类推。

第8行:LD_PRELOAD是一个环境变量,其指定的动态库加载等级最高。@表示第二个参数之后的全部参数。

综上所述,我们就可以确定curl程序是优先加载liblevelip.so库来使用了,通过这种打桩技术,我们可以在加载阶段替换部分系统函数的调用,比如我们常用的socket接口。

liblevelip.c文件

liblevelip.so库由liblevellip.c文件编译而来,该文件在tools文件夹中,我们逐步来分析一下这个c文件。

__libc_start_main函数

首先是__libc_start_main函数,该函数原本是glibc库里面的函数,curl程序里面的main函数就是从这里开始被调用。但是我们在liblevelip.c里面实现了这个函数,并且liblevelip.so的库加载顺序优先于glibc的动态库加载。因此在执行curl程序中的main函数之前,此函数先被执行。如下图:

第3行:dlsym函数里的第一个参数为RTLD_NEXT,这意味着我们将从其他动态库去加载__libc_start_main函数符号(比如glibc库),然后把函数句柄赋值给__start_main变量。

第7~22行:从glibc库中加载一部分linux系统原生提供的系统调用接口。因为我们的网络服务还是要依赖于一些更底层的系统调用接口的。

第24行:初始化一个链表节点lvlip_socks。

第26行:调用glibc的原生__libc_start_main接口。

socket函数

接下来就是liblevelip.so对外提供的第一个网络编程接口--socket函数了。该函数实现如下:

第3~5行:检查网络通信协议族是否为tcp协议,如果不是tcp协议,则调用内核提供的网络服务。

第9行:借助tcp本地套接字接口,与tcp协议栈建立连接,用于通信的本地文件为/tmp/lvlip.socket

第11行:申请一个lvlip_sock类型的buff用于管理socket信息。结构体类型如下:

struct lvlip_sock { struct list_head list; int lvlfd; /* For Level-IP IPC */ int fd;};

list成员变量为链表结点

lvlfd记录与tcp协议栈通信的网络文件描述符

fd记录tcp协议栈的返回状态发送socket消息给tcp协议栈第12行:记录与tcp协议栈通信的网络文件描述符到sock->lvlfd第13行:把这次的网络通信消息加入lvlip_socks链表中第14行:网络通信消息数量加1第16行:获取当前线程的pid号

第17~18行:申请ipc_msg+ipc_socket结构体长度的buff,用于发送详细的socket信息到tcp协议栈。结构体定义如下:

struct ipc_msg { uint16_t type; pid_t pid; uint8_t data[];} __attribute__((packed));

type:记录此次socket信息的具体类型

pid:记录请求网络服务的进程pid号

data:存放具体的通信内容

struct ipc_socket { int domain; int type; int protocol;} __attribute__((packed));

实际上就是soket函数的三个参数。

第23~29行:把ipc_socket作为通信的具体内容填充到ipc_msg的data区域中去

第31行:调用transmit_lvlip()函数真正给tcp协议栈发送消息,并且等待协议栈的数据回复。

此处我们就把liblevelip.so中的socket函数给剖析清楚了,其他诸如close、connect、write、read、send、sendto、recv、此处我们就把liblevelip.so中的socket函数给剖析清楚了,其他诸如close、connect、write、read、send、sendto、recv、此处我们就把liblevelip.so中的socket函数给剖析清楚了,其他诸如close、connect、write、read、send、sendto、recv、recvfrom、poll、select等函数,原理都是一样的,此处不再展开分析。

tcp协议栈(level-ip)

用户空间的level-ip协议栈,在运行之初,就已经在main函数里面创建了一系列线程。如下图:

其中第9行,在run_threads()函数里创建了一系列线程,如下图:

在这里,我们重点关注第5行创建的start_ipc_listener线程

该线程的实现如下:

第5行:指定tcp本地通信的路径文件为"/tmp/lvlip.socket",与我们前面liblevelip.so库的本地通信文件一致,这就说明它们之间确实是通过tco本地通信接口来通信的

第10行:调用socket接口开始进行tcp本地通信

第24行:调用bind函数绑定本地通信路径

第31行:调用listen函数监听指定端口,等待liblevelip.so库发起连接

第46行:如果liblevelip.so库发起连接,则调用accept函数准备开始收发信息。

第54行:每监听到一个新的连接,新创建一个socket_ipc_open函数来进行数据的具体收发。

socket_ipc_open函数主要是负责通信信息的读取,然后根据通信消息的类型不同,来进一步调用具体的处理函数,其实现如下:

第7行:调用read函数进行数据的读取

第8行:调用具体指令的回调信息

demux_ipc_socket_call的函数非常简单,实现如下:

前面我们在liblevelip.so库中调用socket()函数的时候,发送的消息类型为IPC_SOCKET,所以在此处我们进一步分析ipc_socket()这个函数。

它的具体实现如下:

我们重点是关注第7行的_socket函数,该函数就是tcp协议栈的核心接口之一了,它是整个tcp协议栈的真正入口,我们以后再来专门分析这个接口。然后第9行,ipc_write函数负责把tcp协议栈的处理结果返回给liblevelip.so库,代码较为简单,此处不再分析。

原文标题:Linux系统中间件的巧妙实现--以用户空间的tcp协议栈为例

文章出处:【微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    88

    文章

    11628

    浏览量

    217949

原文标题:Linux系统中间件的巧妙实现--以用户空间的tcp协议栈为例

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    为什么会有TCP/IP协议

    在世界上各地,各种各样的电脑运行着各自不同的操作系统大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别。 就好像圣经中上帝打乱了各地人的口音,他们无法合作一样。计算机使用者意识到
    发表于 12-03 06:28

    飞凌嵌入式ElfBoard-常用的网络服务的搭建之SSH服务搭建

    SSHSecure Shell的缩写,由IETF的网络小组(Network Working Group)所制定的建立在应用层基础上的安全协议。SSH是较可靠,专为远程登录会话和其他
    发表于 10-24 08:48

    飞凌嵌入式ElfBoard-常用的网络服务的搭建之NFS服务搭建

    的选择。通过NFS服务,主机将用户指定的目录通过网络共享给目标机(和windows的文件网络共享类似)。目标机可以直接运行存放于Linux主机共享目录下的二进制程序,这样调试
    发表于 10-22 09:23

    飞凌嵌入式ElfBoard-常用的网络服务的搭建之TFTP服务搭建

    网络服务搭建和测试时,ubuntu的网络模式需要设置桥接模式,电脑主机、ubuntu主机、开发板三者的ip要处于同一网段。关闭ubuntu和windows防火墙(关闭ubuntu防火墙:sudo
    发表于 10-21 11:29

    飞凌嵌入式ElfBoard-Linux系统基础入门-网络相关shell命令之网络基础知识

    的参考模型。 在OSI七层结构中,每一层规定了不同的特性,负责不同的功能: 应用层(Application Layer):用户接口,应用程序提供访问网络服务的接口,
    发表于 10-09 09:30

    全球应用加速服务如何实现?网络服务推荐排行榜

    和提高访问速度,同时提供安全防护和负载均衡功能。本文将深入解析全球应用加速服务的实现方式,并为您呈现2025年网络服务提供商排行榜。一、全球应用加速
    的头像 发表于 09-10 09:48 1580次阅读
    全球应用加速<b class='flag-5'>服务</b>如何实现?<b class='flag-5'>网络服务</b>推荐排行榜

    什么是Modbus TCP协议

    TCP/IP协议,通过以太网进行通信,并支持多个设备同时访问同一个Modbus TCP服务器。 一、
    的头像 发表于 07-23 17:18 3267次阅读
    什么是Modbus <b class='flag-5'>TCP</b><b class='flag-5'>协议</b>

    【嘉楠堪智K230开发板试用体验】网络收发信息

    本次实验通过在 K230 上实现基于 Socket 的 TCP 客户端通信,成功与电脑服务器建立连接并实现数据收发。掌握了 Socket 编程的基本流程,加深了对 TCP/IP 协议
    发表于 07-13 08:13

    教你如何手搓一个树莓派网络服务器!

    使用树莓派的定义和好处网络服务器是指利用HTTP及其他协议进行数据传输,处理通过万维网提交的客户端请求的软硬件组合。网络服务器的主要功能是存储、处理并向客户端(通常是网页浏览器)传送网
    的头像 发表于 07-12 08:23 371次阅读
    教你如何手搓一个树莓派<b class='flag-5'>网络服务</b>器!

    51+单片机TCP-IP+协议ZLIP源码

    概述 单片机上网技术,是当前的一个热门技术。单片机上网技术中的一个重要部分是在单片上实现 TCP/IP 协议。现在可获得的 TCP/IP 源代码一般并不为 51 单片机设计,而 51
    发表于 04-22 15:11

    《DNESP32S3使用指南-IDF版_V1.6》第四十七章 lwIP初探

    是一个分层结构的模型,每一层负责不同的网络功能。整个协议可以被分为四层,从上到下分别是:应用层、传输层、网络层和网络接口层。1,应用层:这
    发表于 02-07 09:28

    TCP协议的性能测试与评估方法

    在现代网络通信中,TCP协议的性能对用户体验至关重要。性能测试与评估可以帮助我们了解TCP协议在不同网络
    的头像 发表于 01-22 10:03 2208次阅读

    TCP协议的常见应用场景

    在现代通信网络中,TCP协议因其可靠性和稳定性而被广泛应用于各种场景。 1. 网页浏览 1.1 HTTP和HTTPS HTTP(超文本传输协议) :
    的头像 发表于 01-22 09:55 3296次阅读

    TCP协议网络通信中的应用

    在当今数字化时代,网络通信已经成为我们日常生活和工作中不可或缺的一部分。TCP协议作为网络通信的基石,确保了数据能够在不同设备之间可靠地传输。 一、
    的头像 发表于 01-22 09:50 1121次阅读

    什么是TCP协议及其工作原理

    协议之一。它提供了一种可靠的、有序的、基于字节流的数据传输服务TCP协议的主要特点包括: 面向连接 :在数据传输之前,
    的头像 发表于 01-22 09:41 2198次阅读