select服务器
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/socket.h>
#define MAX_FD sizeof(fd_set)*8 //需要进行等待的文件描述符数组最大值
#define INIT -1 //文件描述符数组初始化值
//文件描述符数组初始化
void AddryInit(int array[], int num )
{
int i = 0;
for(; i < num; ++i)
{
array[i] = INIT;
}
}
//往文件描述符数组中添加新的需要等待的文件描述符
void AddryAdd(int array[], int num ,int fd)
{
int i = 0;
for(; i < num; ++i)
{
if(array[i] == INIT)
{
array[i] = fd;
return;
}
}
}
//往可读文件描述符集中添加文件描述符
int ReadFdSet(int listen_sock, int array[], int num , fd_set* read_set)
{
int i = 0;
FD_SET(listen_sock, read_set);
int max = listen_sock;
for(; i < num; ++i)
{
if(array[i] != INIT)
{
FD_SET(array[i], read_set);
if(max < array[i])
{
max = array[i];
}
}
}
return max;
}
//绑定端口号,将套接字设置为监听状态
int StartUp(int port)
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr = INADDR_ANY;
socklen_t len = sizeof(local);
if(bind(sock,(struct sockaddr*)&local, len) < 0)
{
perror("bind");
exit(2);
}
if(listen(sock,5) < 0)
{
perror("listen");
exit(3);
}
return sock;
}
//从文件描述符数组中删除文件描述符
void AddryDel(int array[], int num, int i)
{
if(i < num)
{
array[i] = INIT;
}
}
//服务函数
void Service(int listen_sock,fd_set* read_set, int array[],int num)
{
int i = 0;
for(; i < num ; ++i)
{
if(array[i] != INIT && FD_ISSET(array[i],read_set))
{
if(array[i] == listen_sock)
{
struct sockaddr_in client;
socklen_t len = sizeof(client);
int client_sock = accept(listen_sock,(struct sockaddr*)&client, &len);
if(client_sock < 0)
{
perror("accept");
continue;
}
AddryAdd(array,num,client_sock);
}
else
{
char buf[1024];
ssize_t s = read(array[i], buf, sizeof(buf)-1);
if(s > 0)
{
buf[s] = 0;
printf("Client> %s\n",buf);
}else if(s == 0)
{
printf("client quit...\n");
AddryDel(array,num,i);
}else
{
perror("read");
}
}
}
}
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
printf("Usage: [%s] [port]\n",argv[0]);
return 1;
}
int listen_sock = StartUp(atoi(argv[1]));
int array[MAX_FD];
AddryInit(array,MAX_FD);
AddryAdd(array,MAX_FD,listen_sock);
fd_set read_set;
FD_ZERO(&read_set);
struct timeval timeout = {5,0};
for(;;)
{
int max = ReadFdSet(listen_sock,array, MAX_FD, &read_set);
switch(select(max+1,&read_set,NULL,NULL,&timeout))
{
case 0:
sleep(2);
printf("select timeout...\n");
break;
case -1:
perror("select");
break;
default:
Service(listen_sock,&read_set,array,MAX_FD);
break;
}
FD_ZERO(&read_set);
}
}
poll服务器
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <sys/socket.h>
//将poll_fd结构体存储到一个数组中
#define MAX_FD 1024 //需要进行等待的文件描述符数组最大值
#define INIT -1 //文件描述符数组初始化值
//poll_fd数组初始化
void Init(struct pollfd* fd_list, int num )
{
int i = 0;
for(; i < num; ++i)
{
fd_list[i].fd = INIT;
fd_list[i].events = 0;
fd_list[i].revents = 0;
}
}
//往文件描述符数组中添加新的需要等待的文件描述符
void Add(struct pollfd* fd_list, int num ,int fd)
{
int i = 0;
for(; i < num; ++i)
{
if(fd_list[i].fd == INIT)
{
fd_list[i].fd = fd;
fd_list[i].events = POLLIN;
return;
}
}
}
//绑定端口号,将套接字设置为监听状态
int StartUp(int port)
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr = INADDR_ANY;
socklen_t len = sizeof(local);
if(bind(sock,(struct sockaddr*)&local, len) < 0)
{
perror("bind");
exit(2);
}
if(listen(sock,5) < 0)
{
perror("listen");
exit(3);
}
return sock;
}
//服务函数
void Service(int listen_sock,struct pollfd* fd_list,int num)
{
int i = 0;
for(; i < num ; ++i)
{
if(fd_list[i].fd != INIT && fd_list[i].revents & POLLIN )//对应的文件描述符上的读事件就绪
{
if(fd_list[i].fd == listen_sock)
{
struct sockaddr_in client;
socklen_t len = sizeof(client);
int client_sock = accept(listen_sock,(struct sockaddr*)&client, &len);
if(client_sock < 0)
{
perror("accept");
continue;
}
Add(fd_list,MAX_FD,client_sock);
}
else
{
char buf[1024];
ssize_t s = read(fd_list[i].fd, buf, sizeof(buf)-1);
if(s > 0)
{
buf[s] = 0;
printf("Client> %s\n",buf);
}else if(s == 0)
{
printf("client quit...\n");
close(fd_list[i].fd);
fd_list[i].fd = INIT;
}else
{
perror("read");
}
}
}
}
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
printf("Usage: [%s] [port]\n",argv[0]);
return 1;
}
int listen_sock = StartUp(atoi(argv[1]));
struct pollfd fd_list[MAX_FD];
Init(fd_list,MAX_FD);
Add(fd_list,MAX_FD,listen_sock);
for(;;)
{
switch(poll(fd_list,MAX_FD,1000))
{
case 0:
sleep(2);
printf("select timeout...\n");
break;
case -1:
perror("select");
break;
default:
Service(listen_sock,fd_list,MAX_FD);
break;
}
}
}
epoll服务器(LT模式)
ET模式的epoll服务器还没写,等写完了再放上来。。。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <string.h>
#define MAXEVENTS 10
//打印提示手册
void Usage()
{
printf("Usage: ./epoll_server.c [port]\n");
exit(0);
}
//创建监听套接字
int StartUp(int port)
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
if(bind(sock,(struct sockaddr*)&server, sizeof(server)) < 0)
{
perror("bind");
exit(2);
}
if(listen(sock,5) < 0)
{
perror("listen");
exit(3);
}
return sock;
}
//服务函数
void Server(int listen_sock, int epoll_fd, struct epoll_event re_epoll_event[], int num)
{
int i = 0;
for(;i < num;++i)
{
if(re_epoll_event[i].events & EPOLLIN){
if(re_epoll_event[i].data.fd == listen_sock && re_epoll_event[i].events & EPOLLIN)
{
struct sockaddr_in client;
socklen_t len = sizeof(client);
int client_sock = accept(re_epoll_event[i].data.fd,(struct sockaddr*)&client,&len);
if(client_sock < 0)
{
perror("accept");
continue;
}
printf("Client[%s] accept success!\n",inet_ntoa(client.sin_addr));
struct epoll_event event;
event.data.fd = client_sock;
event.events = EPOLLIN | EPOLLOUT;
epoll_ctl(epoll_fd,EPOLL_CTL_ADD,client_sock,&event);
continue;
}
else
{
char buf[1024];
buf[0] = '\0';
ssize_t s = recv(re_epoll_event[i].data.fd,buf,sizeof(buf)-1,0);
if(s > 0)
{
buf[s] = '\0';
printf("Client> %s\n",buf);
send(re_epoll_event[i].data.fd,buf,strlen(buf),0);
continue;
}else if(s == 0)
{
printf("Client quit\n");
epoll_ctl(epoll_fd,EPOLL_CTL_DEL,re_epoll_event[i].data.fd,NULL);
close(re_epoll_event[i].data.fd);
continue;
}
else
{
perror("recv");
continue;
}
}
}
}
}
int main(int argc, char* argv[])
{
if(argc != 2)
Usage();
int listen_sock = StartUp(atoi(argv[1]));
//创建epoll模型
int epoll_fd = epoll_create(MAXEVENTS+1);
if(epoll_fd == -1)
{
perror("epoll_create");
return 1;
}
//向epoll模型中添加文件描述符并注册事件
struct epoll_event epoll_event;
epoll_event.events = EPOLLIN;
epoll_event.data.fd = listen_sock;
//接收epoll_wait返回值
if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock,&epoll_event ) < 0)
{
perror("epoll_ctl");
return 2;
}
for(;;)
{
struct epoll_event re_epoll_event[MAXEVENTS];
int ret = epoll_wait(epoll_fd,re_epoll_event,MAXEVENTS,-1);
switch(ret)
{
case 0:
printf("epoll_wait timeout...\n");
break;
case -1:
perror("epoll_wait");
break;
default:
Server(listen_sock,epoll_fd,re_epoll_event,ret);
break;
}
}
return 0;
}