c/c++:端口复用(setsockopt)、io多路转接(select、 poll、epoll)

目录1. 端口复用setsockopt函数2. IO多路转接2.1selectselect函数演示:io多路转接(select函数)服务器代码模板3.2poll2.3 epollepoll_create 创建函数epoll_ctl 控制函数epoll_wait检测函数2.4 epoll 的工作模式2.4.1LT模式(默认)epoll...
摘要由CSDN通过智能技术生成

目录

1. 端口复用

setsockopt函数

2. IO多路转接

2.1 select

select函数演示:

io多路转接(select函数)服务器代码模板

3.2 poll

2.3  epoll

epoll_create 创建函数

epoll_ctl 控制函数

epoll_wait 检测函数

2.4 epoll 的工作模式

2.4.1 LT模式(默认)

epoll LT模式实现的io多路转接 服务器端代码模板示例:

2.4.3 ET模式(边沿触发模式)

epoll ET模式实现的io多路转接 服务器端代码模板示例:


 

1. 端口复用

端口复用最常用用途:

  • 防止服务器重启时之前绑定的端口还未释放
  • 程序突然退出而系统没有释放端口

 

setsockopt函数

setsockopt函数有很多功能,这里只讲端口复用的功能。

#include <sys/types.h> 
#include <sys/socket.h>
// 设置套接字属性
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
	参数:
	- sockfd: 要操作的文件描述符
	- level: 级别 -> SOL_SOCKET (端口复用的级别)
        - optname: 端口复用的级别(二选一,随便选,对于端口复用都可以)
        	- SO_REUSEADDR
        	- SO_REUSEPORT
        - optval: 端口复用-> 对应的是整形数
        	- 1: 可以复用
        	- 0: 不能复用
        - optlen: optval参数对应的内存大小

// 设置端口复用, 设置的时机: 服务器绑定端口之前, 设置端口复用。例如:
setsockopt();
bind();

 

2. IO多路转接

使用进程/线程方式实现并发:
        - 共同点: 
            有一个父亲线程/进程 -> accept 某些情况下是阻塞的
            子进程/子线程   -> 通信 -> read/write 某些情况下是阻塞的
        - 不同点:
            线程更节省系统资源, 一般写程序, 考虑线程的实现方式
            在一个进程中, 调用另一个进程 -> exec
进程/线程方式实现并发代码模板:https://blog.csdn.net/qq_35883464/article/details/103643720

改进思路: 所有的阻塞状态, 程序猿都不去判断, 委托内核判断, 得到内核回复之后进行后续处理
    - 程序猿是不能直接操作内核, 间接 -> 使用系统函数
        - select
        - poll
        - epoll

IO多路转接核心思想: 不再由应用程序自己监视客户端连接和数据通信,取而代之由内核替应用程序监视文件。

 

2.1 select

select主旨思想:

  1. 先构造一张有关文件描述符的列表, 将要监听的文件描述符添加到该表中
  2. 调用一个函数,监听该表中的文件描述符,直到这些描述符表中的一个进行I/O操作时,该函数才返回。
  3. 函数对文件描述符的检测操作是由内核完成的
  4.  
  5. 在返回时,它告诉进程有多少(哪些)描述符要进行I/O操作。
#include <sys/select.h>
#include <unistd.h>

// sizeof(fd_set) = 128

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
	参数:
        - nfds: 委托内核检测的最大文件描述符的值 + 1
        - readfds: 读集合, 委托内核检测哪些文件描述符的读属性(读的是对方发送过来的数据)
        	- 传入传出的参数
        - fd_set: 写集合, 委托内核检测哪些文件描述符的写属性
        	- 传入传出的参数
        	- 委托内核检测写缓冲区是不是还可以写数据(不满就可以写)
        - exceptfds: 异常集合, 委托内核检测哪些文件描述符出现了异常
            - 传入传出的参数

       	- timeout:
struct timeval {
    long    tv_sec;         /* 秒 */
    long    tv_usec;        /* 毫秒 */
};
			- NULL: 永久阻塞, 直到检测到了文件描述符有变化
			- tv_sec = 0, tv_usec = 0, 不阻塞
			- tv_sec > 0 || tv_usec > 0, 阻塞对应的时间长度
	返回值:
		-1: 失败
		>0(n): 检测的集合中有n个文件描述符发送的变化 

// 将参数文件描述符fd对应的标志位, 设置为0
void FD_CLR(int fd, fd_set *set);

// 判断fd对应的标志位到底是0还是1, 返回值: fd对应的标志位的值, 0, 返回0, 1->返回1
int  FD_ISSET(int fd, fd_set *set);

// 将参数文件描述符fd对应的标志位, 设置为1
void FD_SET(int fd, fd_set *set);

// fd_set 共有1024bit, 全部初始化为0
void FD_ZERO(fd_set *set);

 

select函数演示:

fd_set表是自己设置的,和文件描述符表一样。

值为1:要读的文件描述符。值为0:不关心的文件描述符。

之后,select会修改文件描述符表,值为1:要读的文件描述符有数据。值为0:不关心的文件描述符和没有数据的文件描述符。

 

io多路转接(select函数)服务器代码模板

图示代码流程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/i
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值