您的位置:首页 > 其它

C/S通信---服务器IO多路复用模型之epoll的使用

2015-11-04 13:52 561 查看
服务端代码:

#include<stdio.h>

#include<sys/socket.h>

#include<unistd.h>

#include<sys/types.h>

#include<errno.h>

#include<string.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<netinet/in.h>

#include<stdlib.h>

#include<sys/epoll.h>    //mac下不支持,可以使用kqueue

int main()

{

int socket_fd,connect_fd;

struct sockaddr_in servaddr, cliaddr;

char buff[3];

struct epoll_event ev;

struct epoll_event events[4096];

int n;

int acceptCount = 0;

socklen_t socklen = sizeof(struct sockaddr_in);

//create socket

if((socket_fd = socket(AF_INET,SOCK_STREAM,0)) == -1)

{

printf("create socket error!\n");

exit(0);

}

//set local address

memset(&servaddr,0,sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr.sin_port = htons(8000);

//bind the local addr to socket

if(bind(socket_fd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1)

{

printf("bind error %d!\n",errno);

exit(0);

}

//listen client

if(listen(socket_fd,10) == -1)

{

printf("listen error\n");

exit(0);

}

printf("wait for client connection!\n");

/* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */

int kdpfd = epoll_create(4096);

ev.events = EPOLLIN | EPOLLET;

ev.data.fd = listenfd;

if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, socket_fd, &ev) < 0)

{

fprintf(stderr, "epoll set insertion error: fd=%d\n", socket_fd);

return -1;

}

int curfds = 1;

while(1){

/* 等待有事件发生 */

int nfds = epoll_wait(kdpfd, events, curfds, -1);

if (nfds == -1)

{

perror("epoll_wait");

continue;

}

/* 处理所有事件 */

for (n = 0; n < nfds; ++n)

{

if (events
.data.fd == socket_fd)

{

int connfd = accept(socket_fd, (struct sockaddr *)&cliaddr,&socklen);

if (connfd < 0)

{

perror("accept error");

continue;

}

sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);

printf("%d:%s", ++acceptCount, buf);

if (curfds >= 4096) {

fprintf(stderr, "too many connection, more than %d\n", 4096);

close(connfd);

continue;

}

if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)

{

perror("setnonblocking error");

}

ev.events = EPOLLIN | EPOLLET;

ev.data.fd = connfd;

if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0)

{

fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno));

return -1;

}

curfds++;

continue;

}

// 处理客户端请求

if (handle(events
.data.fd) < 0) {

epoll_ctl(kdpfd, EPOLL_CTL_DEL, events
.data.fd,&ev);

curfds--;

}

}

}

close(socket_fd);

return 0;

}

int handle(int connfd) {

int nread;

char buf[4096];

nread = read(connfd, buf, 4096);//读取客户端socket流

printf("%s\n",buf);

if (nread == 0) {

printf("client close the connection\n");

close(connfd);

return -1;

}

if (nread < 0) {

perror("read error");

close(connfd);

return -1;

}

write(connfd, buf, nread);//响应客户端

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: