用select实现多路IO复用
wrap.c见多进程服务器-cainaiozjz
#include <stdio.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include "wrap.h"
#include <sys/time.h>
#define SIZE 1024
#define PORT 8000
char *IP = "192.168.68.152";
// select多路IO复用
int main()
{
//创建监听套接字
int lfd = Socket(AF_INET, SOCK_STREAM, 0);
// 将监听套接字与IP:PORT绑定
struct sockaddr_in s_addr;
s_addr.sin_port = htons(PORT);
s_addr.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.68.152", &s_addr.sin_addr.s_addr);
socklen_t len = sizeof(s_addr);
Bind(lfd, (struct sockaddr*)&s_addr, len);
// 监听套接字开始监听
Listen(lfd, 128);
// 此时只有监听套接字需要select检查
fd_set old_set, read_set;
FD_ZERO(&old_set);
FD_ZERO(&read_set);
FD_SET(lfd, &old_set);
int max_fd = lfd;
while (1)
{
read_set = old_set;
// 有文件描述符发生变化,select检查出
int n = select(max_fd + 1, &read_set, NULL, NULL, NULL);
if(-1 == n)
{
perror("select");
return 1;
}
else if(0 == n)
continue;
// 先检查监听套接字是否有新连接
if(FD_ISSET(lfd, &read_set))
{
struct sockaddr_in c_addr;
int sfd = Accept(lfd, (struct sockaddr*)&c_addr, &len);
FD_SET(sfd, &old_set);
max_fd = sfd > max_fd ? sfd : max_fd;
// 欢迎新连接
char _ip[16] = "";
printf("%s : %d连接成功\n", inet_ntop(AF_INET, &c_addr.sin_addr.s_addr, _ip, 16),
ntohs(c_addr.sin_port));
}
// 检查所有已连接的套接字
for(int fd = lfd + 1; fd <= max_fd; ++fd)
{
if(FD_ISSET(fd, &read_set))
{
char buf[SIZE];
bzero(buf, SIZE);
int n = read(fd, buf, SIZE);
if(n < 0) // read 出错
{
perror("read");
close(fd);
FD_CLR(fd, &old_set);
if(fd == max_fd)
--max_fd;
}
else if(n == 0) // fd 套接字关闭, 在 oldset里置零
{
FD_CLR(fd, &old_set);
close(fd);
printf("socket closed\n");
if(fd == max_fd)
--max_fd;
}
else // 打印信息
{
printf("%s\n", buf);
Write(fd, buf, n);
}
}
}
}
return 0;
}

浙公网安备 33010602011771号