tcp 通过poll实现socket 回射服务器

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<signal.h>
#include<sys/wait.h>
#include<poll.h>  
#include<sys/stropts.h>

#define MAXLINE 1024
#define OPEN_MAX  128 
#define ERR_EXIT(m)     do {  perror(m);   exit(EXIT_FAILURE); } while (0)

int main(int argc, char **argv)
{
	int listenfd, connfd, sockfd;
	int i, maxi, nready;
	ssize_t n;
	char buf[MAXLINE];
	socklen_t clilen;
	struct pollfd client[OPEN_MAX];
	struct sockaddr_in cliaddr, servadd;

	if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		ERR_EXIT("socket error");
	}

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

	servadd.sin_family = AF_INET;
	servadd.sin_port = htons(49160);
	servadd.sin_addr.s_addr = htonl(INADDR_ANY);
	//if((inet_pton(AF_INET, "127.0.0.1", &servadd.sin_addr))<0)
	//	ERR_EXIT("inet_pton error");

	if (bind(listenfd, (struct sockaddr *)&servadd, sizeof(servadd))<0)
	{
		ERR_EXIT("bind error");
	}

	if (listen(listenfd, SOMAXCONN) < 0)
	{
		ERR_EXIT("listen error");
	}

    client[0].fd = listenfd;
    client[0].events = POLLRDNORM;
    for (i = 1; i < OPEN_MAX; ++i)
    {
    	client[i].fd = -1;
    }
    maxi = 0;
    for ( ; ; ){
    	//内核监听事件,如果有就绪事件立马返回
    	//INFTIM没有定义,直接写成-1即可
    	printf("阻塞到poll#########\n");
    	nready = poll(client, maxi+1,-1);
    	//该if条件代表监听client的接入
    	if (client[0].revents & POLLRDNORM){
    		clilen = sizeof(cliaddr);
    		connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
    		for (i = 1; i < OPEN_MAX; ++i){
    			if (client[i].fd < 0){
    				client[i].fd = connfd; //保存已经连接的描述符
    				break;
    			}
    		}
    		if (i == OPEN_MAX){
    			ERR_EXIT("too many clients");
    		}

    		client[i].events = POLLRDNORM;
    		if (i>maxi){
    			maxi = i;
    		}
    		printf("###nread:%d\n", nready);
    		if (--nready <= 0){
    			printf("继续监听连接描述符的事件\n");
    			continue; //继续监听连接描述符的事件.
    		}
    	}
    	printf("检查nready事件:%d,maxi:%d\n", nready,maxi);
		//检查所有的clients 数据的写入
		for (i = 1; i <= maxi; ++i){
			if((sockfd = client[i].fd) < 0){
				continue;//继续坚持可用的client描述符
			}
			//内核通过revents返回描述符的状态给应用(client端往server端写入了数据)
			if (client[i].revents &(POLLRDNORM | POLLERR)){
				//每次read 必须把buf重新清零,不然缓存中原有的旧数据
				//会被重新写入到client端
				memset(buf, 0, sizeof(buf));
				if ((n = read(sockfd, buf, MAXLINE))<0){
					if (errno == ECONNRESET)
					{
						//connnection reset by client
						printf("connection reset by client\n");
						close(sockfd);
						client[i].fd = -1;
					}else{
						printf("read error\n");
					}
				}else if (n == 0){
					//connection closed by client
					printf("connection closed by client\n");
					close(sockfd);
					client[i].fd = -1;
				}else{
					printf("send data to client,data: %s\n", buf);
					write(sockfd,buf,n);
				}

				if (--nready <=0 ){
					break;
				}
			}
		}
    }
}
发布了77 篇原创文章 · 获赞 6 · 访问量 9333

猜你喜欢

转载自blog.csdn.net/ding283595861/article/details/104436048
今日推荐