城南花已开.jpg
码龄7年
关注
提问 私信
  • 博客:53,521
    动态:11
    53,532
    总访问量
  • 72
    原创
  • 1,534,769
    排名
  • 18
    粉丝
  • 0
    铁粉
IP属地以运营商信息为准,境内显示到省(区、市),境外显示到国家(地区)
IP 属地:北京市
  • 加入CSDN时间: 2017-08-08
博客简介:

城南花已开的博客

查看详细资料
个人成就
  • 获得69次点赞
  • 内容获得22次评论
  • 获得198次收藏
  • 代码片获得121次分享
创作历程
  • 70篇
    2020年
  • 2篇
    2019年
成就勋章
TA的专栏
  • linux网络编程
    30篇
  • c++
    2篇
  • linux系统编程
    18篇
  • 每日一题
    22篇
  • c语言
    1篇
  • 搜索
    1篇
创作活动更多

HarmonyOS开发者社区有奖征文来啦!

用文字记录下您与HarmonyOS的故事。参与活动,还有机会赢奖,快来加入我们吧!

0人参与 去创作
  • 最近
  • 文章
  • 代码仓
  • 资源
  • 问答
  • 帖子
  • 视频
  • 课程
  • 关注/订阅/互动
  • 收藏
搜TA的内容
搜索 取消

基础回顾----listen函数的backlog参数的本质

在初学网络编程这块时,对listen函数的第二个参数(backlog)简单理解为服务器允许同时连接的客户端个数,但后面总是感觉对这个参数的意义很模糊,在查阅资料后才发现这个参数远远没有表面上那么简单,因此写篇博客总结、记录、巩固一下。先提出两个概念半连接状态队列(syns queue)和完全连接状态队列(accept queue),通过下图可以看到这两个队列的作用:图片来源:关于TCP 半连接队列和全连接队列可以看到linux会将处于SYN_RCVD状态的socket放在半连接队列中,将已经建议好连
原创
发布博客 2020.08.12 ·
2217 阅读 ·
8 点赞 ·
1 评论 ·
23 收藏

为何static不能在类中定义而static const却能在类中定义?

有时候类会声明在头文件中,static 成员变量是属于类的而不属于类实例化的对象,所以若在类中定义static成员变量就与不能在头文件中定义变量的规则冲突。但是为什么static const却能在类中定义呢?因为static const 成员变量会被编译器优化,为编译期常量,编译器不会为其分配内存,更像是宏定义那样,在编译期时,在使用它的地方,用它的值替换它,这一点可以通过代码看到,若我们在类中定义一个static const 成员变量,我们可以打印出它的值,却不能打印出它的地址,因为编译器并没有给它分配内
原创
发布博客 2020.08.10 ·
775 阅读 ·
2 点赞 ·
1 评论 ·
1 收藏

进程池实现----高效的半同步/半异步并发模式的进程池

为何要用进程池?当我们在写并发服务器时,若每当一个客户端连接请求到来时,我们就为其创建一个进程来服务。这样动态的创建进程,无疑是比较耗时的,这将导致较慢的客户端相应。进程池的概念在服务器启动前我们就创建一组进程,我们将这组进程在逻辑抽象成一个池子。当我们需要一个工作进程来处理新到来的客户端请求时,我们可以直接从进程池中取得一个执行实体(进程),而无需动态的调用fork函数来创建进程。相比于动态创建子进程,选择一个已经存在的子进程代价显然要小得多。至于主进程如何选择子进程,有两种方式:主进程使用某
原创
发布博客 2020.08.09 ·
423 阅读 ·
0 点赞 ·
0 评论 ·
3 收藏

sendmsg和recvmsg的应用----在进程之间传递描述符

在进程之间传递描述符,我们通常会想到fork一个子进程,通过子进程继承父进程打开的描述符,来实现进程之间传递描述符。但是有时候我们需要子进程向父进程传递描述符,或者在没有血缘关系的两个进程之间传递文件描述符,比如客户端向服务端请求打开某个文件或者设备,服务端进行打开操作并把描述符传递给客户端,这样对客户端屏蔽了打开文件或者设备的细节。我们应当注意的是这里传递的描述符不是数值,而是发送描述符进程的PCB中文件描述符表里以该文件描述符为索引的元素----指向File结构体的指针对于上面描述的需求,Linux
原创
发布博客 2020.07.30 ·
1013 阅读 ·
2 点赞 ·
0 评论 ·
8 收藏

Linux进程间通信----信号量

学过操作系统的话,对信号量应该熟悉。当多个进程同时访问计算机资源时,我们需要考虑进程同步问题,以确保任一时刻只有一个进程可以拥有独占式的访问。通常程序对共享资源访问的代码只是很短的一段,但就是这很短的一段代码引发了进程同步问题,我们将这段代码称为临界区。进程同步就是确保任一时刻只有一个进程进入临界区。信号量原语是操作系统为进程同步提供的一种手段。一、什么是信号量信号量是一种特殊的变量,他只能取自然数值,并且只支持两种操作,即p、v操作。假设我们当前有信号量sv。p操作:访问信号量sv,若其值大于0,则
原创
发布博客 2020.07.21 ·
285 阅读 ·
0 点赞 ·
0 评论 ·
1 收藏

最小堆的实现及应用-----定时器(3):时间堆

基于升序链表的定时器和时间轮都是以固定的频率来调用心搏函数,并在其中依次检测到期的定时器,然后执行到期定时器上的回调函数,这样的定时并不准确,因为可能已有定时器到期了,但是因为心搏函数此时还未调用而无法处理定时任务。设计定时器的另一种思路是:将所有定时器中超时时间最小的一个定时器的超时值作为心搏间隔。这样,一旦心博函数tick被调用,超时时间最小的定时器必然到期,我们就可以在tick函数中处理该定时器。然后,再次从剩余的定时器中找出超时值最小的一个,并将这个设置为下一心博间隔。如此反复,就可以实现较为精准
原创
发布博客 2020.07.20 ·
949 阅读 ·
1 点赞 ·
0 评论 ·
4 收藏

定时器(2)---时间轮

上一文所说的基于排序链表的定时器在添加定时器时效率很低,而时间轮则解决了这个问题,下图为一个简单的时间轮:指针指向一个槽(slot),其以恒定的速度顺时针转动,每转动一下就指向下一个槽,每次转动称为一个滴答(tick)。一个滴答的时间称为时间轮的槽间隔si(slot interval),它实际为心搏时间。该时间轮有N个槽,其运转一周的时间为N×siN\times siN×si。每个槽指向一条定时链表,每条链表上的定时器具有一个相同的特征:即他们的定时时间相差N×siN\times siN×si的整数倍。
原创
发布博客 2020.07.18 ·
274 阅读 ·
0 点赞 ·
1 评论 ·
2 收藏

定时器(1)---基于升序双向链表定时器处理非活动连接

一个高性能服务器通常需要处理非活动连接,来提升性能和释放计算机资源,我们可以为每个客户端设置一个定时器,其中包含超时时间,处理函数以及函数的参数。通过升序双向链表将所有客户端的定时器组织起来,通过alarm函数定时,当SIGALRM信号到来时,遍历链表来调用超时客户端的回调函数来关闭非活动连接。下面通过代码来展示这一方法。定时器代码:list_time.h:#ifndef _LIST_TIME_H#define _LIST_TIME_H#include<time.h>#inclu
原创
发布博客 2020.07.18 ·
596 阅读 ·
0 点赞 ·
0 评论 ·
0 收藏

收不到SIGURG信号?

在写利用SIGURG信号处理带外数据时,程序老是收不到该信号,找了很长时间BUG,在网上也搜不到相关内容,所以在此记录一下,防止后面的人跟我踩的是一样的坑,当然这种错误可能就我一个人会犯。我收不到的原因是,SIGURG信号捕捉函数是在accept之后注册的,而客户端发送数据是建立连接后立即开始发送数据的,并且发完数据就直接关闭连接退出了,而服务端检测到对端关闭后也会释放资源退出,这会导致两种情况:1.当带外数据到达时,SIGURG信号的捕捉函数还没注册上,服务端采用的是默认处理动作,即忽略。2.带外数
原创
发布博客 2020.07.02 ·
557 阅读 ·
9 点赞 ·
6 评论 ·
5 收藏

带外数据

带外数据什么是带外数据TCP的带外数据TCP带外数据的发送过程TCP带外数据的接受过程默认接受方式另一种接收方式应用程序如何接受和发送带外数据应用程序检查带外数据是否到达的方法I/O复用系统调用的异常事件SIGURG信号什么是带外数据带外数据用于迅速告诉对方本端发生的重要事情。它比普通数据有更高的优先级,它应该总是立即被发送,不论发送缓冲区中是否有排队等待发送的普通数据。带外数据的传输可以使用一条独立的传输层连接,也可以映射到传输普通数据的连接中。udp没有实现带外数据传输,TCP也没有真正的带外数据,
原创
发布博客 2020.07.02 ·
987 阅读 ·
5 点赞 ·
0 评论 ·
10 收藏

EINTR

当程序在执行处于阻塞状态的系统调用时接收到信号,并且我们为该信号设置了信号处理函数,在信号处理函数返回后,程序将面临继续执行或不执行慢速系统调用两种选择,默认情况下是系统调用将被中断,并且errno被设置为EINTR。我们可以选择继续执行,有以下两种方法:1.在设置信号处理函数的时候,为信号设置SA_RESTART标志以自动重启被该信号中断的系统调用,但是该方法对某些慢速系统调用无效,比如epoll_wait,poll,seletc等慢速系统调用,即使给信号设置了该选项,也会被中断。具体对那些慢速系统调用
原创
发布博客 2020.06.30 ·
1574 阅读 ·
2 点赞 ·
0 评论 ·
11 收藏

信号的一种处理模式----统一事件源

信号是一种异步事件:信号处理函数和程序的主循环是两条不同的执行路线。我们希望信号处理函数尽快地执行完毕,以确保该信号不会屏蔽(为了避免一些竟态条件,信号在处理期间,系统不会再次触发它)太久。(由于信号集采用位图这种数据结构,导致在我们屏蔽该信号期间 ,无论该信号到达多少次,我们只能记录一次,所以在当前信号处理函数执行完后,该信号只能触发一次,这当然不是我们希望的,所以信号处理函数执行的越快,越能避免这种问题。)为了使信号处理函数执行的速度变快,我们可以将处理函数的主逻辑放在程序的主循环中,当信号处理函数被
原创
发布博客 2020.06.30 ·
252 阅读 ·
0 点赞 ·
0 评论 ·
0 收藏

用poll来实现群聊功能

客户端:#include<stdio.h>#include<sys/socket.h>#include<sys/poll.h>#include<sys/types.h>#include<arpa/inet.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<unistd.h>#include<fcnt
原创
发布博客 2020.06.29 ·
162 阅读 ·
0 点赞 ·
0 评论 ·
0 收藏

UDP SOCKET 读数据的注意事项

UDP是数据报协议,它的数据单位与TCP不同,是以一个报文为单位,所以我们读取数据时应当注意应用缓冲区的大小,若不能接受一个报文中全部的数据,那么该报文没有被读取到的数据会丢失。...
原创
发布博客 2020.06.28 ·
371 阅读 ·
1 点赞 ·
0 评论 ·
0 收藏

I/O复用的高级应用三:同时处理TCP和UDP服务

对于同一个端口,如果服务器要同时处理该端口上的TCP和UDP请求,则需要建立两个不同的socket,一个是流socket,另一个是数据报socket,并将它们都绑定到该端口上。下例回射服务器就能同时处理一个端口上的TCP和UDP请求:#include<stdio.h>#include<sys/socket.h>#include<sys/epoll.h>#include<sys/types.h>#include<unistd.h>#in
原创
发布博客 2020.06.28 ·
301 阅读 ·
0 点赞 ·
0 评论 ·
2 收藏

使用POLLRDHUP和EPOLLRDHUP事件的坑

这两个事件其实是一个东西,分别对应poll和epoll,通常用来判断对端是否关闭,但是当你对某个socket注册POLLIN和POLLRDHUP(EPOLLIN和EPOLLRDHUP)时,在对端关闭时,对于poll来说会一直触发POLLIN + POLLRDHUP事件,epoll也会触发EPOLLIN + EPOLLRDHUP事件,是否一直触发要看epoll是工作在LT模式下还是ET模式下。所以,当我们使用POLLRDHUP(EPOLLRDHUP)事件来判断对端是否关闭时,POLLRDHUP(EPOLLR
原创
发布博客 2020.06.27 ·
3166 阅读 ·
2 点赞 ·
0 评论 ·
8 收藏

I/O复用的高级应用----非阻塞connect

在使用非阻塞connect时,常常会发生EINPROGRESS错误。这是在对非阻塞desocket调用connect,而连接又没有立即建立的情况下发生的错误,在这种情况下,我们可以调用select、poll等函数来监听这个连接失败的socket上的可写事件。当select、poll等函数返回后,再利用getsockopt来读取错误码并清楚该socket上的错误。如果错误码是0,表示连接成功建立,否则连接失败。非阻塞connect的实现:#include<stdio.h>#include&l
原创
发布博客 2020.06.26 ·
211 阅读 ·
0 点赞 ·
0 评论 ·
0 收藏

epoll在并发编程中同步问题的解决-----EPOLLONESHOT事件

无论epoll处于LT模式还是ET模式下,一个socket上的某个事件都可能会被触发多次。这在并发编程中会引起一个问题,比如一个线程在读取完某个socket上的数据后开始处理数据,而在处理数据的过程中又触发可读事件,这样会有另外一个线程读取新的数据,这样就会出现两个线程同时操作一个socket的问题。上述问题可以通过epoll中的EPOLLONESHOT事件来解决,对于注册EPOLLONESHOT事件的文件描述符来说,只会触发一次事件,除非使用epoll_ctl函数重置该文件描述符上注册的EPOLLONE
原创
发布博客 2020.06.25 ·
699 阅读 ·
1 点赞 ·
0 评论 ·
2 收藏

用有限状态机处理http请求

#include<stdio.h>#include<sys/socket.h>#include<sys/types.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<arpa/inet.h>//主状态机有两种状态,当前正在分析请求行,当前正在分析头部字段enum CHECK_STATE{CHECK_STATE_REQUESTLIN
原创
发布博客 2020.06.24 ·
593 阅读 ·
0 点赞 ·
0 评论 ·
2 收藏

tee函数

tee函数在两个管道文件描述符之间复制数据,也是零拷贝操作,它不消耗数据,所以其源文件描述符上的数据仍然可用于后续的读操作,其函数原型如下:ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);其参数和上篇splice函数的参数意义相同,但是fd_in和fd_out必须是管道文件描述符,函数成功返回在两个文件描述...
原创
发布博客 2020.04.21 ·
660 阅读 ·
0 点赞 ·
0 评论 ·
0 收藏
加载更多