C语言socket编程-select


前言

在早期的Unix系统中,每个进程都有一个单独的I/O流,这种方式效率低下,因为每个I/O操作都需要等待数据的到来。为了提高效率,Unix引入了select函数,它可以同时监听多个文件描述符,随着网络通信的发展,select函数也被广泛应用于网络编程中,它可以同时监听多个网络连接,当其中任意一个连接有数据到来时,就可以进行相应的处理,从而实现高效的网络通信。


一、简介

在socket编程中,select是一种多路复用 I/O 模型,它可以同时监视多个文件描述符的读写状态,当某个文件描述符就绪时,select会返回该文件描述符,从而实现异步 I/O。

二、select的工作原理

1.工作原理:

  • 服务端初始化socket,绑定端口,监听端口
  • 将sockfd和clientpool中有效的句柄添加到fdset中,调用select等待句柄就绪
  • 客户端初始化socket,发送建链请求
  • 服务端select中感知到sockfd已就绪,函数返回,调用accept与客户端完成建链,并生成connfd,再将connfd添加到clientpool中
  • 客户端向服务端发送数据
  • 服务端遍历clientpool,接收数据,并向客户端返回响应
  • 客户端传输数据完成后断开连接
  • 服务端收到断链事件后,将句柄从clientpool中移除
    在这里插入图片描述

2.fd_set数据模型

  • 假设fd_set长度为1字节(实际使用时根据操作系统而定),fd_set中每一位对应一个句柄fd,1字节长度的fd_set可以表示8个句柄
  • 初始化fd_set set; FD_ZERO(&set),set可以表示为0000 0000
  • 若有fd = 1;执行FD_SET(fd, &set)后,set可以表示为0000 0010
  • 若再加入fd = 3, fd = 5; 执行FD_SET后,set可以表示为0010 1010
  • 执行select(sockFd, &set, NULL, NULL, NULL)后代码会阻塞在这里等待句柄就绪
  • 若此时句柄1和句柄5都发生可读事件,则select函数返回,set此时为0010 0010。没有事件发生的句柄3被清空

三、常用函数及说明

void FD_ZERO(fd_set *set);  		// 初始化集合,使所有位都置为0
void FD_SET(int fd, fd_set *set);   // 将句柄fd添加到集合中
void FD_CLR(int fd, fd_set *set);   // 从集合中删除句柄fd
int FD_ISSET(int fd, fd_set *set);  // 判断句柄fd是否在集合中

四、代码示例

#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <errno.h>

#define ERR 1
#define OK 0
#define ADDR "127.0.0.1"        // 本地IP
#define PORT 23                 // 本地端口
#define BACKLOG 1024            // 监听队列长度
#define MAX_SIZE 1024           // 接收数据缓冲区长度
#define CLIENT_NUM 10           // 可以同时连接的客户端数量

int g_clientFds[CLIENT_NUM] = {
   
   0};

/**
* @brief 输出fd_set当前存储状态
*/
void PrintFdSet(fd_set *
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值