
高性能网络设计
文章平均质量分 61
服务器与客户端、多线程高并发、TCP/IP通信
海绵波波107
务必要疯狂地拥抱雄心,同时要疯狂地真诚
Gitcode地址:https://gitcode.com/qq_43920838
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
zerotier实现内网穿透(访问内网服务器)
然后再在ragflow项目中,docker部署好之后,需要http://服务器Ip:80。此时内网穿透就可以将托管好的Ip输入,然后就能访问内网的服务器上的项目了。有了网络之后,会给你一个网络id,这个网络id是非常重要的,其它设备要加入的这个网络,就需要这个网络id,所以还是很重要的,点击这个id就可以进入具体的设置。加入成功会有200的状态码,而且网页上能够检查到。在windows下安装zerotier客户端,然后用主机去访问托管ip的内网,可以访问成功。然后加入网络中,Id是刚刚在网页中给的。原创 2024-12-09 15:46:48 · 1870 阅读 · 0 评论 -
内网Ip与外网Ip
从这个路由表中可以看出,enp3s0是主要的物理网络接口,它连接到10.0.0.0/22这个更大的网络,并且有一个默认网关10.0.0.1。公司领导给了我一台服务器ip是36.103.xxxxxx,通过xshell可以远程连接上去,连上之后是一个ubuntu系统,当我通过ifconfig查询ip时,发现ip是10.0.0.241是一个内网地址,这是什么原因,为什么查出来不是36.103.xxxxxx呢?但请注意,公网IP地址通常是由ISP(互联网服务提供商)分配的,并且需要正确的网络配置和路由设置。原创 2024-12-09 15:32:49 · 614 阅读 · 0 评论 -
集群聊天服务器面试问题
上来要先做一个2-5分钟的自我介绍,看语言表达能力。开发工作中,只有20%的时间在做开发,其他时间都在开会议讨论方案。1、基本情况()。2、喜欢开发(看什么书,C++ Primer、计算机网络、操作系统原理),然后我还经常上github、csdn、bilibili这些技术类的网站看或者去提问题。而且我喜欢边学习边在CSDN写博客。我对于开发工作,希望自己能够积累工作经验和技术经验,能够在公司岗位上发挥自己的价值,希望能越走越高。表达逻辑、自学能力的介绍、未来工作计划这三个方面。原创 2024-11-27 20:07:28 · 1272 阅读 · 0 评论 -
Webserver回顾
从请求队列中取出request请求,然后process处理process是处理业务代码,用于解析http请求的。原创 2024-11-21 23:17:12 · 500 阅读 · 0 评论 -
集群聊天服务器(14)github发布
说是拒绝连接,手动删除.gitconfig下的代理信息。空文件夹传不上去,在build下面随便创建一个。鼓捣了半天,是因为开了VPN所以连不上。然后把内容都移到这个远程的文件夹中。再push,github密码要生成。查找本机的ipv6地址。原创 2024-11-19 17:19:55 · 585 阅读 · 0 评论 -
集群聊天服务器(13)redis环境安装和发布订阅命令
redis是存键值对的,还可以存链表、数组等等复杂数据结构。github上下载压缩包传到ubuntu中,然后make。头文件那里一直找不到,反复搞json配置文件。上报就是一个通道加上字符串(具体内容)然后重启了一下vscode,就不报错了。而且数据是在内存上存储的,效率非常高。C++对应的则是hiredis。然后把动态库拷贝到lib目录下。订阅通道号以及发布消息。先启动redis服务。默认在6379端口上。原创 2024-11-18 20:48:40 · 754 阅读 · 0 评论 -
集群聊天服务器(12)nginx负载均衡器
weight是权重的意思,权重都为1,那就是轮询,给两台服务器发送。max_fails是心跳机制,等待服务器回消息,等待时间30s,如果心跳超过3次都失败,那么就判定该服务器挂了。nginx从1.9版本之后支持tcp的长连接负载均衡,但是默认没有编译tcp负载均衡模块,编写时需要加入-with-stream参数来激活这个模块。集群部署的服务器之间进行通信,最好的方式就是引入中间件消息队列,解耦各个服务器,使整个系统松耦合,提高服务器的响应能力,节省服务器的带宽资源。在其中一个客户端登录,一个服务器响应了。原创 2024-11-18 18:44:11 · 1057 阅读 · 0 评论 -
Webserver(1.7)模拟实现ls -l命令
能够查看所有文件的信息。原创 2024-10-29 11:42:37 · 324 阅读 · 0 评论 -
Webserver(5.5)解析HTTP请求报文
读取到了请求报文Win64;;v=b3;q=0.6。原创 2024-11-08 19:03:39 · 292 阅读 · 0 评论 -
集群聊天服务器(9)一对一聊天功能
首先注册了信号,回调函数,来处理异常状态。没有绑定事件处理器的话消息会派发不出去。服务器ctrl+c,自动重置用户状态了。业务类中重置用户状态,调用数据库类方法。数据库操作类中,就是更新用户状态。聊天其实是服务器做一个中转。登录李四,收到了离线消息。离线表中的数据也随之删除。现在同时登录两个账号。声明中提供接口和方法。张三对离线的李四说话。原创 2024-11-15 21:29:01 · 573 阅读 · 0 评论 -
集群聊天服务器(6)网络模块代码和业务模块解耦合
在.hpp中声明然后在.cpp中实现的时候,必须要在函数前面加。原创 2024-11-15 09:57:45 · 248 阅读 · 0 评论 -
Webserver(1.6)Linux系统IO函数
stat直接获取指向的文件的信息(哪怕前面有软链接,也会指向最终那个文件信息)写的文件和读取的文件大小一样,在vscode中查看内容一样,拷贝成功。拓展文件长度的时候,需要写一次数据,可以加入一个空的字符串。把文件全部读取并全部写到另一个文件中,拷贝操作。lstat用于获取指向该文件的软链接的信息。下面介绍拓展文件长度的用法。获取当前文件指针位置。原创 2024-10-29 11:13:09 · 467 阅读 · 0 评论 -
Webserver(3.1)线程
必须确保多个线程不会同时修改同一变量,或者某一线程不会读取正在由其他线程修改的变量。pthread_join是一个阻塞的行为,子线程没结束时不会回收的,不会执行。这段代码的执行应该为原子操作,不能被其他线程中断。线程取消不是立马终止,而是遇到取消点的时候终止。对共享数据的操作同一个时间只能一个线程。30就结束了,因为到达了取消点。编译时需要加-pthread。线程同步会降低效率,但是安全。分离之后,就不能进行连接了。会产生卖同一张门票的情况。主线程和子线程交替运行。原创 2024-11-04 21:32:56 · 411 阅读 · 0 评论 -
集群聊天服务器(10)添加好友业务
做到现在,就明显感觉到解耦合是什么意思了,在业务层不出现数据库操作的代码,而是使用一个model类对象去写数据库操作的代码,这样的话业务层只需要直接调用Model类接口。由于model类太多了,然后我们将这些Model相关文件都放到model文件夹中,并在cmakelists中添加这个头文件路径。然后定义好群组Model之后,在业务头文件中添加Model对象。定义groupmodel的头文件接口,以及具体实现。然后再写业务代码,调用数据对象类接口。friendmodel类接口。添加好友也添加进去了。原创 2024-11-17 17:19:33 · 349 阅读 · 0 评论 -
Webserver(5.3)线程池实现
相比于动态地创建子线程,选择一个已经存在的子线程的代价显然要小得多。池是一组资源的集合,这组资源在服务器启动之初就被完全创建好并初始化,这称为静态资源。当服务器执行完之后,把相关的资源放回池中,无需执行系统调用释放资源。线程间竞争的不是CPU的计算资源而是IO,IO的处理一般较慢。创建一个webserver目录。原创 2024-11-08 11:50:38 · 471 阅读 · 0 评论 -
Webserver(2.6)有名管道
管道读端没有被全部关闭,管道已经满了,write会阻塞,管道未满,write将数据写入,并返回实际写入的字节数。读端关闭了,还在写数据,会产生信号,因为没有读端了还写数据,管道会破裂,所以产生信号立马终止。2.一个为只写而打开一个管道的进程会阻塞,直到另一个进程为只读打开管道(与上一个相对)1.一个为只读而打开一个管道的进程会阻塞,直到另外一个进程为只写打开管道。管道中无数据,管道写端被全部关闭,read返回0(相当于读到文件末尾)管道读端被全部关闭,进程会异常终止,进程会收到sigpipe信号。原创 2024-10-31 16:41:50 · 613 阅读 · 0 评论 -
Webserver(2.4)进程控制
这样就会导致一个问题,如果父进程不调用wait()或waitpid()的话,那么保留的那段信息就不会释放,但是系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程,此即为僵尸进程的危害,应当避免。每当出现一个孤儿进程的时候,内核就把孤儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。子进程的父进程的Id变成了1,孤儿进程的父进程会给进程号为1 的Init。Z+的状态就是僵尸进程,仍占据一个进程号,然而进程号是有限的。原创 2024-10-30 18:58:29 · 888 阅读 · 0 评论 -
Webserver(2.5)进程间通信(匿名管道)
子进程也能读自己读的数据,所以需要加sleep(),cpu时间片给父进程,让父进程去读。但是开发的时候,不可能写上sleep。进程间通信的目的:数据传输、通知事件(进程终止时要通知父进程,下载完了要告诉其他子进程,可以把所有内容播放了)、资源共享(涉及互斥和同步)、进程控制(GDB调试进程,控制了run进程)而且这个read是阻塞的,管道默认是阻塞的,如果管道中没有数据,read阻塞,如果管道满了,write阻塞。但是,进程不是孤立的,不同的进程需要进行信息的交互和状态的传递等,因此需要进程间通信。原创 2024-10-31 11:17:49 · 938 阅读 · 0 评论 -
Webserver(2.3)exec函数族
c语言中没有重载,因为不允许同名函数一系列功能相似的函数称为函数族exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容。程序在运行的时候,fork一个子进程,然后在子进程中调用exec,替换成指定的可执行文件。因为当前的进程执行exec把本身内容替换掉不合理。所以先创建子进程再执行execexec函数族执行成功不会返回,只有调用失败了,才会返回-1.原创 2024-10-30 15:08:59 · 312 阅读 · 0 评论 -
Webserver(2.6)信号
还有个问题就是,如果在捕捉信号注册还没完成的时候,子进程就已经全部结束了,那这个时候就不会再发生sigchld了,那就不会被回收了。每一个进程只有唯一的一个定时器,如果第二次出现alarm(重新倒计时),返回值是上一个剩余的时间。然后父进程捕捉该信号,再去调用pid来wait回收资源,之后父进程继续做自己的事情。以上三种情况,内核会发送SIGCHLD信号给父进程,父进程默认忽略该信号。设置阻塞信号集,信号注册完之前,子进程阻塞,信号发不了。捕捉到信号之后,信号忽略,原先终止,现在啥都不做。原创 2024-11-01 17:52:28 · 1127 阅读 · 0 评论 -
Webserver(1.5)GDB
可以set listsize 20,来一次能够查看20行代码。停在这,显示的第8行还没有执行,可以按c继续执行到下一个断点。如何在每一次执行都能自动打印变量的值,不一遍一遍输print。用gdb查看,会默认显示main函数所在的cpp文件的代码。但并没有显示完整,可以继续输入list,一次显示10行。再用enable/ena 断点编号可以设置有效。n就代表不可用,虽然打了断点但是不可用。跳出循环,循环内不能有断点或者断点不可用。还可以制定函数名,从某个函数开始显示。还可以加行号,从多少行开始显示。原创 2024-10-28 15:19:56 · 350 阅读 · 0 评论 -
Webserver(4.4)多进程/多线程实现并发服务器
子进程:完成通信,接收一个客户端连接,就创建一个子进程用于通信。要实现TCP服务器处理并发的任务,使用多线程或者多进程来解决。同时开启两个客户端,会交叉接收信息。父进程负责等待并接受客户端的连接。这样就支持了并发,多个客户端。一个父进程,多个子进程。原创 2024-11-06 20:44:55 · 559 阅读 · 0 评论 -
Webserver(4.5)复用
单边的close,会有一个等待的状态,这个时候有1分钟的时间,端口还开启着。这个时候再打开服务器,可能会有端口依旧绑定的情况。并没有用多进程或者多线程,只使用了select也能完成多客户端的连接。监听文件是否发送数据,告诉进程有哪些描述符需要进行I/O操作。端口复用来重启这个端口,就能重新绑定了。构造一个关于文件描述符的列表。原创 2024-11-07 13:30:10 · 388 阅读 · 0 评论 -
Webserver(4.3)TCP通信实现
四次挥手发生在断开连接的时候,在程序中调用close()会使用TCP协议进行四次挥手。客户端和服务器端都可以主动发起断开连接,和连接的时候不一样(客户端主动)窗口理解为缓冲区的大小,滑动窗口的大小会随着发送数据和接收数据而变化。三次握手发生在客户端连接的时候,在connect()函数调用时。因为三次握手建立的连接是双向的,在断开的时候需要双向断开。通信的双方都有发送缓冲区和接收数据的缓冲区。加上循环就是一直发送。原创 2024-11-06 17:04:46 · 349 阅读 · 0 评论 -
Webserver(1.2)GCC
gcc库不能和c++的库链接,所以统一用g++了。后缀为.c的,gcc当作c,g++当作c++g++可以链接,但在编译阶段会自动调用gcc。test.o能直接运行,相当于exe文件。后缀为.cpp的,两者都认为是c++但是在虚拟机中写代码很不方便。在虚拟机中用gcc编译的命令。将高级语言编译为机器语言。-E 代表进行预处理。g++也可以进行编译。原创 2024-10-25 20:10:27 · 354 阅读 · 0 评论 -
Webserver(4.8)UDP、广播、组播
每个广播消息都包含一个特殊的IP地址,这个IP中子网内主机标志部分的二进制全部为1。192.168.10.最后一位255可以发给所有人。向子网中多台计算机发送消息,只能向局域网发送。客户端需要加入多播组,才能接收到多播的数据。组播既可以用于局域网,也可以用于广域网。客户端需要绑定服务器广播使用的端口。客户端从部分数据才开始接收。原创 2024-11-07 19:12:00 · 500 阅读 · 0 评论 -
集群聊天服务器(2)Json介绍
大家之间交流用json,想要发送数据,就把数据序列化成json,想要接收数据,就反序列化成自己程序的语言。原创 2024-11-13 15:16:55 · 602 阅读 · 0 评论 -
Webserver(1.1)Linux开发环境搭建
先在虚拟机中安装openssh-server。打开vmtool,把压缩包拖到桌面。在windows端可以编辑虚拟机。用归档管理器打开,左上角提取。还有net-tools。原创 2024-10-24 17:26:11 · 409 阅读 · 0 评论 -
Webserver(5.6)服务器压力测试
webbench首先fork多个子进程,每个子进程都循环做web访问测试。每分钟浏览91万个页面,每秒钟243万个字节,总共请求7万多次,1个失败。webbench是linux上一款知名的优秀的web性能压力测试工具。测试处在相同硬件上,不同服务的性能以及在不同硬件上同一个服务的运行状况。展示服务器的两项内容:每秒钟响应请求数和每秒钟传输数据量。测试一下7000个并发。以这个请求访问服务器。原创 2024-11-08 19:33:17 · 520 阅读 · 0 评论 -
Webserver(3.2)锁
同时去读共享资源没有问题,但是互斥锁的排他性太强了,读没有影响,互斥锁读都不行。3个线程不定时写一个全局变量,其余5个线程不定时的读一个全局变量。虽然解决了数据安全的问题,但效率降低了,变成串行。不同的线程卖出几十张之后,切换到另一个线程来卖。接上一章,卖票存在线程安全问题。8个线程操作同一个全局变量。多线程对多个锁进行操作时。未解锁会无法切换线程。原创 2024-11-05 10:50:17 · 408 阅读 · 0 评论 -
Webserver(2.1)进程
程序不占用CPU,进程占用程序要运行起来,操作系统需要分配资源,比如内存、cpu,进程就是操作系统为程序运行的一些资源。进程是基本的分配单元,也是基本的执行单元。可以用一个程序来创建多个进程,进程是由内核定义的抽象实体,并为该实体分配用以执行程序的各项系统资源。单道程序,在计算机内存中只允许一个的程序运行。多道程序设计技术,在计算机内存中同时存放几道相互独立的程序,使它们在管理程序控制下,相互穿插运行,两个或两个以上程序在计算机系统中同处于开始到结束之间的状态,这些程序共享计算机系统资源。原创 2024-10-30 13:33:32 · 691 阅读 · 0 评论 -
集群聊天服务器(11)客户端开发
其实就是之前只做服务器时,需要自己写json请求给服务器反序列化,而写客户端就是自己制作json,获取用户输入然后json序列化然后发给服务器。一个是数据库表设计离线消息表的时候,不能将userid设为主键,这样的话只会出现一个消息,离线时同时一个user发几个也只会有一个。然后也能够体会到,在服务器开发的时候,一定要有日志,错误提示,这样遇到问题很好定位。对于我自己来说,是服务器db那边代码用中文乱码报错了,没有转成utf-8。然后我发现是两边的json不对等,一个是toid,一个是to。原创 2024-11-18 15:23:31 · 626 阅读 · 0 评论 -
Webserver(1.4)Makefile
会检查目标与依赖的生成时间,一般目标会比依赖晚,如果依赖比较晚,说明出现更新了。如果第一条规则查询不到依赖会往下查询其他规则,是否有规则是生成这个依赖的。源代码文件.c非常多,怎么一个一个编译?makefile文件能够按照规则自动进行编译。这样clean就不会生成一个特定的文件。命令:通过执行命令对依赖操作生成目标。依赖:生成目标所需要的文件或是目标。自动变量只能在规则的命令中使用。make编译,生成可执行程序。所有规则都服务于第一条规则。目标:最终要生成的文件。再加一个clean规则。原创 2024-10-28 12:03:22 · 364 阅读 · 0 评论 -
Webserver(1.8)操作函数
复制文件描述符,新的文件描述符和旧的指向同一个文件,多个文件描述符可以指向同一个文件。删除一个目录,只能删除框目录,如果有内容的话,要先把内容删掉,然后再调用这个函数。判断某个文件是否有某个权限,或者判断文件是否存在。最终的权限会与umask进行一个&,抹除部分权限。改变工作路径之后,创建文件在新的工作路径下。缩减或者扩展文件的尺寸至指定的大小。会从空闲中找一个最小的文件描述符用。修改权限之后,文件权限改变了。设置/获取文件的状态标志。修改进程的当前工作目录。内容已经被追加到文件中。原创 2024-10-29 17:12:00 · 565 阅读 · 0 评论 -
Webserver(4.1)网络基础
每层协议都将在上层数据的基础上加上自己的头部信息(有时还包括尾部信息),以实现该层的功能,这个过程就称为封装。网卡是一块计算机硬件,每个网卡都有一个成为MAC地址的独一无二的48位串行号(全球都独一无二)IP协议实际上是一套由软件程序组成的协议软件,将各种不同的帧统一转换成IP数据报格式。现在电脑都有多个网卡(以太网卡、无线网卡),MAC如同身份证上的身份证号码,唯一的。端口标识一个进程,进程号不能作为唯一标识,因为他动态变化。物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。原创 2024-11-06 08:54:59 · 260 阅读 · 0 评论 -
集群聊天服务器(8)用户登录业务
这个业务完成两件事,一个是把存储用户通信连接的哈希表删除该用户的键值对2、将用户在数据库里的状态信息由online变成offline。数据库的增删改查的并发操作是由MYSQL来保证的,不需要担心去上锁啥的。在没有任何响应的情况下,连接突然断开了。如果异常退出,并没有发送合法的json。这个表会被多线程访问,所以要考虑它的线程安全问题。C++STL里面并没有考虑线程安全问题。但是问题就是,一登录成功就断开连接了。当出了大括号之后,锁就自动释放。登录且状态变为online。所以需要保存连接信息。原创 2024-11-15 16:53:18 · 870 阅读 · 0 评论 -
Webserver(4.6)poll和epoll
select的缺点在于每次都需要将fd集合从用户态拷贝到内核态,开销很大。每次调用select都需要在内核遍历传递进来的所有fd,这个开销也很大。select支持的文件描述符数量太小了,默认是1024。fds集合不能重用,每次都需要重置。poll就是扩充了select的大小,用一个结构体集合去取代了这个集合。但是再输入一次,会返回nihao,像挤牙膏一样一点一点得到缓冲区的数据。数据没有读完的话会一直通知,这是水平触发模式,直到读完为止。通过一个循环读取和非阻塞文件描述符,可以一次性读取。原创 2024-11-07 17:44:49 · 534 阅读 · 0 评论 -
Webserver(5.2)网页服务器框架
主线程只监听文件描述符上是否有事件发生,有的话就立即将该事件通知工作线程(逻辑单元),将socket可读可写事件放入请求队列,交给工作线程处理。主线程执行数据读写操作,读写完成之后,主线程向工作线程通知这一完成事件。接收、存储,处理来自客户端的HTTP请求,并对其请求做出HTTP响应。需要处理三类事件:IO事件、信号及定时事件。IO处理单元:处理客户连接,读写网络数据。同步IO模型实现reactor模式。网络存储单元:数据库、文件或缓存。请求队列:各单元之间的通信方式。逻辑单元:业务进程或线程。原创 2024-11-08 10:11:03 · 525 阅读 · 0 评论 -
Webserver(2.8)守护进程
每隔2s获取系统时间,将这个时间写入到磁盘文件中。原创 2024-11-04 17:05:06 · 300 阅读 · 0 评论 -
集群聊天服务器(4)CMake
使用CMake构建一个集成的编译环境,不用命令一行一行编写。大型项目文件很多,命令很麻烦。他会生成makefile,makefile太长了,所以用cmake非常棒。根目录下面创建一个CMakeLists.txt。构建项目编译环境,比写makefile简单。然后运行./server。原创 2024-11-14 17:00:38 · 325 阅读 · 0 评论