网络编程:select多路复用监听accept和write函数解除阻塞

select多路复用的使用
特点:作为中介->Select负责管理这两个阻塞的状态->它啥事业不干,专门看这两个阻塞的函数有没有接收数据。
目的:就是让这些有阻塞的函数不会有阻塞(遍历操作)
缺点:其运行机制实质是在里面进行文件的遍历的过程,当遍历的文件多路,耗费的时间变长,效率变低,实时性跟不上

原理图:
在这里插入图片描述
创建流程:
1、创建套接字
2、绑定
3、监听

函数
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
中文解释
int select(最大文件描述符+1, 读文件描述集合, 写文件描述符集合, 异常文件描述符集合, 设置等待时间,NULL表示一直等待直到有响应)
操作文件描述符集合的函数
void FD_CLR(int fd, fd_set *set); 从set集合中把fd清除
int FD_ISSET(int fd, fd_set *set); 判断set中fd是否响应
void FD_SET(int fd, fd_set *set); 把fd添加到set集合中
void FD_ZERO(fd_set *set); 把集合set清空

书写例子
//用select类监听sockfd
int maxfd = sockfd;//保存最大文件描述符
fd_set readfds;//保存读文件描述符集合
int ret = select(maxfd+1, &readfds, NULL, NULL, NULL);

用select多路复用监听accept和write函数解除阻塞的事例代码:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include "cJSON.h"
#include <stdbool.h>
#include <arpa/inet.h>
#define MAXSIZE 100
void *client_thread(void *arg);
sem_t sm;

struct ClientInfo{
   

	int sockfd;
	char id[16];
};

//定义一个结构体数组
struct ClientInfo cinfo[MAXSIZE];

int main(void)
{
   

	//1.创建套接字
	int sockfd =
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 C++ UDP server,使用 select 多路复用监听并接收广播消息: ```c++ #include <iostream> #include <cstring> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <fcntl.h> #include <sys/select.h> using namespace std; int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(8888); addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)); int flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); fd_set read_fds; FD_ZERO(&read_fds); FD_SET(sockfd, &read_fds); while (true) { int ret = select(sockfd + 1, &read_fds, NULL, NULL, NULL); if (ret < 0) { perror("select error"); break; } else if (ret == 0) { continue; } char buf[1024]; int len = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL); if (len == -1) { perror("recvfrom error"); break; } cout << "received: " << buf << endl; } close(sockfd); return 0; } ``` 首先创建一个 UDP socket,并将其绑定到本地地址和端口。然后将 socket 设置为非阻塞模式。 接下来使用 select 多路复用监听 sockfd 上是否有数据可读,如果有则调用 recvfrom 接收数据。最后打印接收到的数据并继续监听。如果出现错误,则打印错误信息并退出循环。 注意,在此示例中,监听的是所有广播消息,如果需要特定的广播地址,请在绑定本地地址时指定。例如: ```c++ addr.sin_addr.s_addr = inet_addr("224.0.0.1"); ``` 这将监听 224.0.0.1 这个广播地址。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值