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=%dn", listenfd );
return -1;
}
curfds = 1;
printf( "epollserver startup, port %d, max connection is %d, backlog is %dn", servPort, MAXEPOLLSIZE, listenq );
for (;;) {
/* 等待有事件发生 */
nfds = epoll_wait( kdpfd, events, curfds, -1 );
if (nfds == -1){
perror("epoll_wait");
continue;
}
printf( "events hAppen %dn", nfds );
/* 处理所有事件 */
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:%dn", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
printf("%d:%s", ++acceptCount, buf);
if( curfds >= MAXEPOLLSIZE ){
fprintf(stderr, "too many connection, more than %dn", 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: %sn", 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 connectionn");
close(connfd);
return -1;
}
if( nread < 0 ){
perror("read error");
close(connfd);
return -1;
}
write( connfd, buf, nread ); //响应客户端
return 0;
}
推荐阅读
- Linux引导101
- 20 个 Linux 终端下的生产力工具
- Linux 中软链接和硬链接的区别
- LINUX系统和Unix系统有什么区别和联系呢?
- 基于Linux系统的高可用中小型网站集群架构说明
- Linux世界——ssh登录安全简单介绍
- Linux下防御DDOS攻击的操作梳理
- Linux系统常用的文件管理命令
- 在 Linux 上检查 MySQL/MariaDB 数据库正常运行时间的三种方法
- 一文带你彻底理解Linux的各种终端类型及概念