目录
处理流程
- 创建监听的套接字 lfd = socket();
- 将监听的套接字和本地的IP和端口绑定 bind()
- 给监听的套接字设置监听 listen()
- 创建一个文件描述符集合 fd_set,用于存储需要检测读事件的所有的文件描述符
- 通过 FD_ZERO() 初始化
- 通过 FD_SET() 将监听的文件描述符放入检测的读集合中
- 循环调用select(),周期性的对所有的文件描述符进行检测
- select() 解除阻塞返回,得到内核传出的满足条件的就绪的文件描述符集合
- 通过FD_ISSET() 判断集合中的标志位是否为 1
- 如果这个文件描述符是监听的文件描述符,调用 accept() 和客户端建立连接
- 将得到的新的通信的文件描述符,通过FD_SET() 放入到检测集合中
- 如果这个文件描述符是通信的文件描述符,调用通信函数和客户端通信
- 如果客户端和服务器断开了连接,使用FD_CLR()将这个文件描述符从检测集合中删除
- 如果没有断开连接,正常通信即可
- 如果这个文件描述符是监听的文件描述符,调用 accept() 和客户端建立连接
服务端代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <algorithm>
int main()
{
printf("%s 向你问好!\n", "IOSelect");
//监听的fd
int lfd = socket(AF_INET, SOCK_STREAM, 0);
if (lfd == -1)
{
perror("socket");
return -1;
}
//绑定端口
sockaddr_in serveraddr;
serveraddr.sin_addr.s_addr = INADDR_ANY;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9999);
int ret=bind(lfd, (sockaddr*)&serveraddr, sizeof(sockaddr_in));
if (ret == -1)
{
perror("bind");
return -1;
}
//设置监听
ret = listen(lfd, 128);
if (ret == -1)
{
perror("listen");
return -1;
}
//rdset为所有的描述符
fd_set rdset;
FD_ZERO(&rdset);
FD_SET(lfd, &rdset);
int maxfd = lfd;
//原始集合rdset因为tmp在select之后可能会被修改
//tmp是传出传入的
fd_set tmp ;
while (1)
{
tmp = rdset;
int num = select(maxfd + 1, &tmp, NULL, NULL, NULL);
if (FD_ISSET(lfd, &tmp))
{
// 此时说明lfd的读缓冲区是有东西的
sockaddr_in cliaddr;
int cliLen = sizeof(cliaddr);
int cfd = accept(lfd,(sockaddr* ) & cliaddr, (socklen_t*)cliLen);
FD_SET(cfd, &rdset);
maxfd = cfd>maxfd?cfd:maxfd;
}
for (int i = 0; i <= maxfd; i++)
{
if (i != lfd && FD_ISSET(i, &tmp))
{
//接收数据
char buf[10] = { 0 };
// 一次只能接收10个字节, 客户端一次发送100个字节
// 一次是接收不完的, 文件描述符对应的读缓冲区中还有数据
// 下一轮select检测的时候, 内核还会标记这个文件描述符缓冲区有数据 -> 再读一次
// 循环会一直持续, 知道缓冲区数据被读完位置
int len = read(i, buf, sizeof(buf));
if (len == 0)
{
printf("客户端关闭了连接...\n");
// 将检测的文件描述符从读集合中删除
FD_CLR(i, &rdset);
close(i);
}
else if (len > 0)
{
// 收到了数据
// 发送数据
write(i, buf, strlen(buf) + 1);
}
else
{
// 异常
perror("read");
}
}
}
}
return 0;
}
标签:lfd,基于,int,rdset,并发,描述符,FD,监听,select
From: https://www.cnblogs.com/liviayu/p/17816193.html