#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;
}
}
}
}
}
tcp 通过poll实现socket 回射服务器
猜你喜欢
转载自blog.csdn.net/ding283595861/article/details/104436048
今日推荐
周排行