
服务器
文章平均质量分 82
冯岳松
这个作者很懒,什么都没留下…
展开
-
README
简单易用的vim配置,熟练后可大大提高开发效率(VS Code的两倍以上)。原创 2023-02-28 12:08:34 · 578 阅读 · 0 评论 -
EasyVim:简单强大的VIM配置
简单易用的vim配置,熟练后可大大提高开发效率(VS Code的两倍以上)。原创 2023-01-12 11:30:43 · 874 阅读 · 0 评论 -
30天自制C++服务器day16-重构服务器、使用智能指针
至此,本教程进度已经过半,在前15天的学习和开发中,相信大家对服务器的开发原则、核心模块的组织有了一个初步的了解,也有能力写出一个“乞丐”版本的服务器。包括内存相关的,如内存泄漏、野指针、悬垂引用等,还有网络编程相关的,如无效socket、连接意外终止、TCP缓冲区满等,还有事件相关的,如epoll、kqueue返回其他错误情况,等等。重构的另一个重点,就是避免资源的复制操作,尽量使用移动语义来进行所有权的转移,这对提升程序的性能有十分显著的帮助,这也是为何rust语言性能如此高的原因。原创 2022-11-04 23:05:35 · 502 阅读 · 0 评论 -
30天自制C++服务器day15-macOS支持、完善业务逻辑自定义
day15-macOS、FreeBSD支持作为程序员,使用MacBook电脑作为开发机很常见,本质和Linux几乎没有区别。本教程的EventLoop中使用Linux系统支持的epoll,然而macOS里并没有epoll,取而代之的是FreeBSD的kqueue,功能和使用都和epoll很相似。Windows系统使用WSL可以完美编译运行源代码,但MacBook则需要Docker、云服务器、或是虚拟机,很麻烦。在今天,我们将支持使用kqueue作为EventLoop类的Poller,使网络库可以在macO原创 2022-02-06 17:34:09 · 1462 阅读 · 1 评论 -
30天自制C++服务器day14-支持业务逻辑自定义、完善Connection类
回顾之前的教程,可以看到服务器Echo业务的逻辑在Connection类中。如果我们需要不同的业务逻辑,如搭建一个HTTP服务器,或是一个FTP服务器,则需要改动Connection中的代码,这显然是不合理的。Connection类作为网络库的一部分,不应该和业务逻辑产生联系,业务逻辑应该由网络库用户自定义,写在server.cpp中。同时,作为一个通用网络库,客户端也可以使用网络库来编写相应的业务逻辑。今天我们需要完善Connection类,支持业务逻辑自定义。首先来看看我们希望如何自定义业务逻辑,这是原创 2022-01-09 16:00:13 · 2066 阅读 · 0 评论 -
30天自制C++服务器day13-C++工程化、代码分析、性能优化
在之前的教程里,我们已经完整开发了一个主从Reactor多线程的服务器的核心架构,接下来的开发重心应该从架构转移到细节。在这之前,将整个项目现代化、工程化是必要的,也是必须的。C++项目工程化的第一步,一定是使用CMake。目前将所有文件都放在一个文件夹,并且没有分类。随着项目越来越复杂、模块越来越多,开发者需要考虑这座屎山的可读性,如将模块拆分到不同文件夹,将头文件统一放在一起等。对于这样复杂的项目,如果手写复杂的Makefile来编译链接,那么将会相当负责繁琐。我们应当使用CMake来管理我们的项目,原创 2022-01-04 22:45:34 · 970 阅读 · 0 评论 -
30天自制C++服务器day12-将服务器改写为主从Reactor多线程模式
在上一天的教程,我们实现了一种最容易想到的多线程Reactor模式,即将每一个Channel的任务分配给一个线程执行。这种模式有很多缺点,逻辑上也有不合理的地方。比如当前版本线程池对象被EventLoop所持有,这显然是不合理的,线程池显然应该由服务器类来管理,不应该和事件驱动产生任何关系。如果强行将线程池放进Server类中,由于Channel类只有EventLoop对象成员,使用线程池则需要注册回调函数,十分麻烦。更多比较可以参考陈硕《Linux多线程服务器编程》第三章今天我们将采用主从Reac原创 2022-01-04 22:44:31 · 922 阅读 · 1 评论 -
30天自制C++服务器day11-完善线程池,加入一个简单的测试程序
在昨天的教程里,我们添加了一个最简单的线程池到服务器,一个完整的Reactor模式正式成型。这个线程池只是为了满足我们的需要构建出的最简单的线程池,存在很多问题。比如,由于任务队列的添加、取出都存在拷贝操作,线程池不会有太好的性能,只能用来学习,正确做法是使用右值移动、完美转发等阻止拷贝。另外线程池只能接受std::function<void()>类型的参数,所以函数参数需要事先使用std::bind(),并且无法得到返回值。为了解决以上提到的问题,线程池的构造函数和析构函数都不会有太大变化,原创 2022-01-04 22:43:55 · 340 阅读 · 0 评论 -
30天自制C++服务器day10-加入线程池到服务器
今天是本教程的第十天,在之前,我们已经编码完成了一个完整的单线程服务器,最核心的几个模块都已经抽象出来,Reactor事件驱动大体成型(除了线程池),各个类的生命周期也大体上合适了,读者应该完全理解之前的服务器代码后再开始今天的学习。观察当前的服务器架构,不难发现我们的Reactor模型少了最关键、最重要的一个模块:线程池。当发现socket fd有事件时,我们应该分发给一个工作线程,由这个工作线程处理fd上面的事件。而当前我们的代码是单线程模式,所有fd上的事件都由主线程(也就是EventLoop线程)原创 2022-01-04 22:43:10 · 840 阅读 · 0 评论 -
30天自制C++服务器day09-缓冲区-大作用
在上一天,我们分离了用于接受连接的Acceptor类,并把新建连接的逻辑放在了Server类中。在上一天我们还提到了Acceptor类最主要的三个特点:类存在于事件驱动EventLoop类中,也就是Reactor模式的main-Reactor类中的socket fd就是服务器监听的socket fd,每一个Acceptor对应一个socket fd这个类也通过一个独有的Channel负责分发到epoll,该Channel的事件处理函数handleEvent()会调用Acceptor中的接受连接函数来原创 2021-12-27 17:12:45 · 199 阅读 · 0 评论 -
30天自制C++服务器day08-一切皆是类,连TCP连接也不例外
在上一天,我们分离了用于接受连接的Acceptor类,并把新建连接的逻辑放在了Server类中。在上一天我们还提到了Acceptor类最主要的三个特点:类存在于事件驱动EventLoop类中,也就是Reactor模式的main-Reactor类中的socket fd就是服务器监听的socket fd,每一个Acceptor对应一个socket fd这个类也通过一个独有的Channel负责分发到epoll,该Channel的事件处理函数handleEvent()会调用Acceptor中的接受连接函数来原创 2021-12-27 01:24:35 · 1340 阅读 · 0 评论 -
30天自制C++服务器day07-为我们的服务器添加一个Acceptor
在上一天,我们分离了服务器类和事件驱动类,将服务器逐渐开发成Reactor模式。至此,所有服务器逻辑(目前只有接受新连接和echo客户端发来的数据)都写在Server类里。但很显然,Server作为一个服务器类,应该更抽象、更通用,我们应该对服务器进行进一步的模块化。仔细分析可发现,对于每一个事件,不管提供什么样的服务,首先需要做的事都是调用accept()函数接受这个TCP连接,然后将socket文件描述符添加到epoll。当这个IO口有事件发生的时候,再对此TCP连接提供相应的服务。在这里务必先理原创 2021-12-27 00:33:12 · 1547 阅读 · 0 评论 -
30天自制C++服务器day06-服务器与事件驱动核心类登场
在上一天,我们为每一个添加到epoll的文件描述符都添加了一个Channel,用户可以自由注册各种事件、很方便地根据不同事件类型设置不同回调函数(在当前的源代码中只支持了目前所需的可读事件,将在之后逐渐进行完善)。我们的服务器已经基本成型,但目前从新建socket、接受客户端连接到处理客户端事件,整个程序结构是顺序化、流程化的,我们甚至可以使用一个单一的流程图来表示整个程序。而流程化程序设计的缺点之一是不够抽象,当我们的服务器结构越来越庞大、功能越来越复杂、模块越来越多,这种顺序程序设计的思想显然是不能满足原创 2021-12-26 17:19:26 · 251 阅读 · 0 评论 -
30天自制C++服务器day05-epoll高级用法-Channel登场
day05-epoll高级用法-Channel登场在上一天,我们已经完整地开发了一个echo服务器,并且引入面向对象编程的思想,初步封装了Socket、InetAddress和Epoll,大大精简了主程序,隐藏了底层语言实现细节、增加了可读性。让我们来回顾一下我们是如何使用epoll:将一个文件描述符添加到epoll红黑树,当该文件描述符上有事件发生时,拿到它、处理事件,这样我们每次只能拿到一个文件描述符,也就是一个int类型的整型值。试想,如果一个服务器同时提供不同的服务,如HTTP、FTP等,那么就原创 2021-12-23 17:12:47 · 1348 阅读 · 1 评论 -
30天自制C++服务器day04-来看看我们的第一个类
day04-来看看我们的第一个类在上一天,我们开发了一个支持多个客户端连接的服务器,但到目前为止,虽然我们的程序以.cpp结尾,本质上我们写的仍然是C语言程序。虽然C++语言完全兼容C语言并且大部分程序中都是混用,但一个很好的习惯是把C和C++看作两种语言,写代码时需要清楚地知道自己在写C还是C++。另一点是我们的程序会变得越来越长、越来越庞大,虽然现在才不到100行代码,但把所有逻辑放在一个程序里显然是一种错误的做法,我们需要对程序进行模块化,每一个模块专门处理一个任务,这样可以增加程序的可读性,也可原创 2021-12-23 16:28:37 · 1229 阅读 · 0 评论 -
30天自制C++服务器day03-高并发还得用epoll
在上一天,我们写了一个简单的echo服务器,但只能同时处理一个客户端的连接。但在这个连接的生命周期中,绝大部分时间都是空闲的,活跃时间(发送数据和接收数据的时间)占比极少,这样独占一个服务器是严重的资源浪费。事实上所有的服务器都是高并发的,可以同时为成千上万个客户端提供服务,这一技术又被称为IO复用。IO复用和多线程有相似之处,但绝不是一个概念。IO复用是针对IO借口,而多线程是针对CPU。IO复用的基本思想是事件驱动,服务器同时保持多个客户端IO连接,当这个IO上有可读或可写事件发生时,表示这个I原创 2021-12-13 15:49:12 · 1369 阅读 · 0 评论 -
30天自制C++服务器day02-不要放过任何一个错误
day02-不要放过任何一个错误github:day02-不要放过任何一个错误在上一天,我们写了一个一个客户端发起socket连接和一个服务器接受socket连接。然而对于socket,bind,listen,accept,connect等函数,我们都设想程序完美地、没有任何异常地运行,而这显然是不可能的,不管写代码水平多高,就算你是林纳斯,也会在程序里写出bug。在《Effective C++》中条款08讲到,别让异常逃离析构函数。在这里我拓展一下,我们不应该放过每一个异常,否则在大型项目开发中一定原创 2021-12-01 11:36:16 · 1073 阅读 · 0 评论 -
30天自制C++服务器day01-从一个最简单的socket开始
day01-从一个最简单的socket开始如果读者之前有计算机网络的基础知识那就更好了,没有也没关系,socket编程非常容易上手。但本教程主要偏向实践,不会详细讲述计算机网络协议、网络编程原理等。想快速入门可以看以下博客,讲解比较清楚、错误较少:计算机网络基础知识总结要想打好基础,抄近道是不可的,有时间一定要认真学一遍谢希仁的《计算机网络》,要想精通服务器开发,这必不可少。首先在服务器,我们需要建立一个socket套接字,对外提供一个网络通信接口,在Linux系统中这个套接字竟然仅仅是一个文件原创 2021-11-30 20:37:23 · 1014 阅读 · 0 评论 -
30天自制C++服务器
先说结论:不管使用什么语言,一切后台开发的根基,是面向Linux的C/C++服务器开发。几乎所有高并发服务器都是运行在Linux环境的,笔者之前也用Java、node写过服务器,但最后发现只是学会了一门技术、一门语言,而并不了解底层的基础原理。一个HTTP请求的过程,为什么可以实现高并发,如何控制TCP连接,如何处理好数据传输的逻辑等等,这些只有面向C/C++编程才能深入了解。本教程模仿《30天自制操作系统》,面向零经验的新手,教你在30天内入门Linux服务器开发。原创 2021-11-30 20:35:52 · 2682 阅读 · 0 评论