Epoll写的一个tcp回射服务器

运行环境:Linux

/* include fig01 */
#include	"unp.h"
#include	<limits.h>		/* for OPEN_MAX */
#include  <sys/epoll.h>
#define INET_ADDRSTRLEN 16
#define OPEN_MAX  FOPEN_MAX
#define NOTDEF
int
main(int argc, char **argv)
{
	int					listenfd, connfd;
	char				buf[MAXLINE];
    char                str[INET_ADDRSTRLEN];
	socklen_t			clilen;
	struct sockaddr_in	cliaddr, servaddr;
    //创建套接字
	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

    //绑定套接字
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family      = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(SERV_PORT);

	Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

    //开启监听
	Listen(listenfd, LISTENQ);

     //step1: epoll开始工作之前 先把文件描述符纳入epoll监管
    struct epoll_event  event;
    event.data.fd=listenfd;
    event.events=EPOLLIN| EPOLLET;    
    int epoll_fd=epoll_create(10);
    epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listenfd,&event);

    
    struct epoll_event events[10];
    printf("run here\n");

/* include fig02 */
	for ( ; ; ) {
        //step2: epoll开始工作 阻塞的等待文件描述符就绪
        int ret=epoll_wait(epoll_fd,events,10,-1);

        //先打印ret的值看看
       // printf("ret=%d\n",ret);

        //step3:epoll完成工作  看各个套接字状态
        if(ret<0){
            //epoll返回-1表示出错
            printf("epoll error\n");
        }
        else if(ret==0){
            //epoll返回0表示超时
            printf("epoll time out\n");
        }
        else{
            //返回的ret>0时 表示就绪的描述符个数
            for(int i=0;i<ret;i++){
                if ( (events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || 
				(!(events[i].events & EPOLLIN))) {
					printf("epoll error\n");
					close(events[i].data.fd);
					continue;
			    }
                else if(events[i].data.fd==listenfd) //有新的连接
                {
                    connfd = Accept(listenfd, (SA *) &cliaddr, &clilen); //accept这个连接
                    //printf("new client\n");
                    printf("new client: %s, port %d\n",
					Inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
					ntohs(cliaddr.sin_port));//输出新连接的地址信息和端口号

                    event.data.fd=connfd;
                    event.events=EPOLLIN|EPOLLET;
                    epoll_ctl(epoll_fd,EPOLL_CTL_ADD,connfd,&event); //将新的fd添加到epoll的监听队列中
                }
    
                else if( events[i].events&EPOLLIN ) //接收到数据,读socket
                {
                    connfd=events[i].data.fd;
                    int bytes = read(connfd,buf,MAXLINE);
                    // 客户端关闭连接
                    if (bytes == 0){
                        ret =epoll_ctl(epoll_fd,EPOLL_CTL_DEL,connfd,NULL);
                        close(connfd);
                        printf("client[%d] closed\n", i);
                    }
                    else
                        write(connfd,buf,bytes);
                }

            }
	    }
        //printf("endif\n");
    }
}
/* end fig02 */

基于《UNIX网络编程》这本书的poll源码改的,整个项目的源码可以看github。
unpv13e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值