基于C++从0到1手写Linux高性能网络编程框架
分享课程——基于C++从0到1手写Linux高性能网络编程框架,2023年新课,附源码+电子书,课程包更新。
Linux在服务器领域有着强大的优势,网络编程便是其中一项重要组成部分,运用合理的技巧可以构建出具有高效率、可靠性和强大可拓展性的网络框架,提高服务器功能和效率。
Linux网络编程技巧可以细分为多个方面,首先网络编程的开始必不可少的是编写好的Socket程序。Socket可以说是传输层协议的核心,它充当网络应用程序之间的接口,能够连接本地服务器与外部服务器,实现进程间的通信接口。在Linux环境下,使用C语言需要引入头文件,调用系统函数socket()来生成socket描述符:
#include
int socket(int domain, int type, int protocol);
其中domain表示网络类型,type表示socket类型,protocol表示协议。
接着还需要调用系统函数connect()来实现客户与服务器之间的连接,函数原型如下:
#include
int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
其中sockfd是函数socket()返回的socket描述符,addr则是字符串“:IP:port”组成的服务器地址,addrlen表示结构体大小。
I/O复用是另外一个Linux网络编程的关键技巧,他使得服务器进程可以同时处理多个客户端的连接,以最大限度的提高效率。
I/O复用的最常用的两个函数就是select、poll。select保持暂停,直到被监视的文件描述符的I/O事件发生,然后调用系统函数select()触发对应的I/O事件,函数原型如下:
#include
int select(int nfds, fd_set* readfds, fd_set* writefds, const struct timeval* timeout);
其中fd_set定义了文件描述符集合,timeout定义了超时时间。
最后使用epoll技术来构建安全且高性能的网络框架,epoll通过实现系统调用把系统的任务调度放置在用户态下来实现任务的高效率和极速反应。epoll系统函数调用原型:
#include
int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
其中epfd是epoll_create()函数返回的结果,op可能值:EPOLL_CTL_ADD、EPOLL_CTL_MOD、EPOLL_CTL_DEL,fd是要操作的socket文件描述符,event是与文件描述符相关联的事件结构体。
综上,Linux网络编程技巧是必不可少的工作,经过这些技巧的组合,可以构建出具有高效率、可靠性和强大可拓展性的网络框架,从而提升服务器的功能和效率,以应好网络的发展。
多进程并发
基本模型:
父进程循环 accept(),阻塞等待。有客户端链接进来,则创建一个子进程去与之通信,父进程继续回去阻塞等待 accept。
父进程中应注册信号捕捉函数捕捉SIGCHILD信号,以便在子进程完成通信后回收它。回收的处理函数应当是一个非阻塞的循环waitpid,有子进程在工作就返回父进程,使其得以继续监听。
注意,执行回调函数回收子进程,相当于一次软中断。而accept() 是会被系统中断打断的,也就是说,等回调函数返回时,accpet会被打断,返回 -1,并设置errno 为 EINTR。要解决这个问题,便要在 accept 的返回值为 -1 时进行一次判断,如果errno == EINTR,则 continue 即可。
linux系统安装配置:
虚拟机安装配置、Ubuntu系统安装配置、vim编辑器安装配置、文件共享配置
系统操作命令:
文件操作命令:ls、touch、mkdir、pwd、rm、chmod、mv、cp、vim、cd、pwd网络操作命令:ping、ifconfig、netstat
服务器搭建:
ftp服务器搭建:服务器操作命令:ftp、open、get、put、cd、byte
nfs服务器搭建项目
一个良好的状态码应该反应出目前action的处理状态,在asp中,我们可以使用controller base的内建函数,使返回的IActionResult携带特定的状态码。比如,在正常情况下,action 应该返回状态码 200, 所以我们可以使用ok函数,不仅可以携带相应数据,routes路线,也可以携带状态码,200 ok。但是,如果变量routes是一个空列表,是不是就意味着找不到资源呢?既然找不到资源,是不是应该返回404呢?这时候,我们就可以使用controller 级别的另一个内建函数,NotFound()。
if (touristRoutes.Count() <= 0)
{
return NotFound("no tourist routes found");
}
接下来,我们再来看看第二个action函数,GetTouristRouteById。添加变量,touristRoutesFromRepo ,如果touristRouteFromRepo 为空
if (touristRouteFromRepo == null)
{
return NotFound();
}
如果不为空,就代表从数据仓库中拿到了数据,我们用ok来做相应数据的状态。
现在让我们运行试试看。
打开旅游路线controller,我们来添加一个新的action函数,CreateTroustRoute()
[HttpPost]
public IActionResult CreateTouristRoute([FromBody] TouristRouteForCreationDto touristRouteForCreationDto)
![QQ截图20231205115815.png](https://static.golangjob.cn/231205/88ab21262ba439db46ad74469df0b495.png)
有疑问加站长微信联系(非本文作者)
![](https://static.golangjob.cn/static/img/footer.png?imageView2/2/w/280)