linux下epoll网络编程模型,Linux IO多路复用之epoll网络编程

前言

本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下:

客户端从标准输入读入一行,发送到服务端

服务端从网络读取一行,然后输出到客户端

客户端收到服务端的响应,输出这一行到标准输出

服务端

代码如下:

#include

#include /* basic system data types */

#include /* basic socket definitions */

#include /* sockaddr_in{} and other Internet defns */

#include /* inet(3) functions */

#include /* epoll function */

#include /* nonblocking */

#include /*setrlimit */

#include

#include

#include

#include

#define MAXEPOLLSIZE 10000

#define MAXLINE 10240

int handle(int connfd);

int setnonblocking(int sockfd)

{

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

return -1;

}

return 0;

}

int main(int argc, char **argv)

{

int servPort = 6888;

int listenq = 1024;

int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0;

struct sockaddr_in servaddr, cliaddr;

socklen_t socklen = sizeof(struct sockaddr_in);

struct epoll_event ev;

struct epoll_event events[MAXEPOLLSIZE];

struct rlimit rt;

char buf[MAXLINE];

/* 设置每个进程允许打开的最大文件数 */

rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;

if (setrlimit(RLIMIT_NOFILE, &rt) == -1)

{

perror("setrlimit error");

return -1;

}

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl (INADDR_ANY);

servaddr.sin_port = htons (servPort);

listenfd = socket(AF_INET, SOCK_STREAM, 0);

if (listenfd == -1) {

perror("can't create socket file");

return -1;

}

int opt = 1;

setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

if (setnonblocking(listenfd) < 0) {

perror("setnonblock error");

}

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

{

perror("bind error");

return -1;

}

if (listen(listenfd, listenq) == -1)

{

perror("listen error");

return -1;

}

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

kdpfd = epoll_create(MAXEPOLLSIZE);

ev.events = EPOLLIN | EPOLLET;

ev.data.fd = listenfd;

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

{

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

return -1;

}

curfds = 1;

printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq);

for (;;) {

/* 等待有事件发生 */

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

if (nfds == -1)

{

perror("epoll_wait");

continue;

}

/* 处理所有事件 */

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

{

if (events[n].data.fd == listenfd)

{

connfd = accept(listenfd, (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 >= MAXEPOLLSIZE) {

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

close(connfd);

continue;

}

if (setnonblocking(connfd) < 0) {

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[n].data.fd) < 0) {

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

curfds--;

}

}

}

close(listenfd);

return 0;

}

int handle(int connfd) {

int nread;

char buf[MAXLINE];

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

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;

}

编译

编译和启动服务端

gcc epollserver.c -o epollserver

./epollserver

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值