这一次贴出epoll的一个简单例子,关于epoll的一些介绍网上很多,我也写了一个简单的介绍:epoll简单介绍
下面分别贴出c和c++的同一份实现代码:用于测试多个客户端和一个服务端的连接
客服端代码:
//tcp server 并发服务器 客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <ctype.h>
#include <arpa/inet.h>
#define SERV_PORT 9999
int tcp_client_init(){
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1){
printf("socket failed!\n");
return -1;
}
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //任意的IP地址
int ret = connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
if(ret == -1){
printf("connect error!\n");
return -2;
}
//connect success
write(sockfd,"connect success\n",20);
while(sockfd != -1){
} //等待
close(sockfd);
return sockfd;
}
int main(){
tcp_client_init();
}
服务端:
C语言:
//tcp server epoll并发服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#define MAX_LINK_NUM 128
#define SERV_PORT 8888
#define BUFF_LENGTH 320
#define MAX_EVENTS 5
int count = 0;
int tcp_epoll_server_init(){
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1){
printf("socket error!\n");
return -1;
}
struct sockaddr_in serv_addr;
struct sockaddr_in clit_addr;
socklen_t clit_len;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);// 任意本地ip
int ret = bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
if(ret == -1){
printf("bind error!\n");
return -2;
}
listen(sockfd,MAX_LINK_NUM);
//创建epoll
int epoll_fd = epoll_create(MAX_EVENTS);
if(epoll_fd == -1){
printf("epoll_create error!\n");
return -3;
}
//向epoll注册sockfd监听事件
struct epoll_event ev; //epoll事件结构体
struct epoll_event events[MAX_EVENTS]; //事件监听队列
ev.events = EPOLLIN;
ev.data.fd = sockfd;
int ret2 = epoll_ctl(epoll_fd,EPOLL_CTL_ADD,sockfd,&ev);
if(ret2 == -1){
printf("epoll_ctl error!\n");
return -4;
}
int connfd = 0;
while(1){
//epoll等待事件
int nfds = epoll_wait(epoll_fd,events,MAX_EVENTS,-1);
if(nfds == -1){
printf("epoll_wait error!\n");
return -5;
}
printf("nfds: %d\n",nfds);
//检测
for(int i = 0;i<nfds;++i){
//客服端有新的请求
if(events[i].data.fd == sockfd){
connfd = accept(sockfd,(struct sockaddr*)&clit_addr,&clit_len);
if(connfd == -1){
printf("accept error!\n");
return -6;
}
ev.events = EPOLLIN;
ev.data.fd = connfd;
if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,connfd,&ev) == -1){
printf("epoll_ctl add error!\n");
return -7;
}
printf("accept client: %s\n",inet_ntoa(clit_addr.sin_addr));
printf("client %d\n",++count);
}
//客户端有数据发送过来
else{
char buff[BUFF_LENGTH];
int ret1 = read(connfd,buff,sizeof(buff));
printf("%s",buff);
}
}
}
close(connfd);
return 0;
}
int main(){
tcp_epoll_server_init();
}
c++:只是进行了一层简单封装,其实没什么区别
#include <iostream>
#include <vector> //向量存储
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
using namespace std;
#define MAX_NUM 1024
class MyEpoll{
public:
MyEpoll();
~MyEpoll();
int epoll_create();
int epoll_add(int listenfd);
int epoll_del(int listenfd);
int epoll_mod(int listenfd);
int myepoll_wait();
struct epoll_event* getEvent();
private:
int epfd;
int epoll_events_max_nums;
struct epoll_event * events; //就绪队列
};
MyEpoll::MyEpoll(){
this->epfd = -1;
this->epoll_events_max_nums = MAX_NUM;
this->events = NULL;
}
MyEpoll::~MyEpoll(){
if(epfd > 0){
close(epfd);
}
if(events != NULL){
delete[] this->events;
this->events = NULL;
}
}
int MyEpoll::epoll_create(){
this->epfd = epoll_create(1);
if(epfd == -1){
printf("epoll_create error\n");
return -1;
}
if(events != NULL){
delete [] events;
}
events = new epoll_event[epoll_events_max_nums];
}
int MyEpoll::epoll_add(int listenfd){
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = listenfd;
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
}
int MyEpoll::epoll_del(int listenfd){
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = listenfd;
epoll_ctl(epfd,EPOLL_CTL_DEL,listenfd,&ev);
}
int MyEpoll::epoll_mod(int listenfd){
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = listenfd;
epoll_ctl(epfd,EPOLL_CTL_MOD,listenfd,&ev);
}
int MyEpoll::myepoll_wait(){
int nfds = epoll_wait(epfd,events,MAX_NUM,-1);
return nfds;
}
struct epoll_event* MyEpoll::getEvent(){
return events;
}
#define SERV_PORT 9999
#define BUFF_LENGTH 320
int main(){
MyEpoll myepoll;
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1){
printf("socket error!\n");
return -1;
}
struct sockaddr_in serv_addr;
struct sockaddr_in clit_addr;
socklen_t clit_len;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);// 任意本地ip
int ret = bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
if(ret == -1){
printf("bind error!\n");
return -2;
}
listen(sockfd,MAX_LINK_NUM);
myepoll.epoll_create();
myepoll.epoll_add(sockfd);
int connfd = 0;
int count = 0;
for(;;){
int nfds = myepoll.myepoll_wait();
if(nfds == -1){
printf("epoll_wait error!\n");
return -5;
}
printf("nfds: %d\n",nfds);
struct epoll_event *events = myepoll.getEvent();
for(int i = 0;i<nfds;++i){
//客服端有新的请求
if(events[i].data.fd == sockfd){
connfd = accept(sockfd,(struct sockaddr*)&clit_addr,&clit_len);
if(connfd == -1){
printf("accept error!\n");
return -6;
}
myepoll.epoll_add(connfd);
printf("accept client: %s\n",inet_ntoa(clit_addr.sin_addr));
printf("client %d\n",++count);
}
else{
char buff[BUFF_LENGTH];
int ret1 = read(connfd,buff,sizeof(buff));
printf("%s",buff);
}
}
}
}