【多路复用-服务器实现】Poll

Poll服务器实现框架

#include <头文件>

int main(int argc, char const *argv[])
{
	lfd = socket();
	bind();
	listen();
	struct pollfd client[OPEN_MAX]; // 声明pollfd结构体
	client[0].fd = lfd; // 要监听的第一个文件描述符
	client[0].events = POLLIN; // lfd监听普通读事件
	for (int i = 1; i < OPEN_MAX; ++i)
		client[i].fd = -1; // 其余表示不可用
	int maxi = 0;
	while(1)
	{
		int nready = poll(client, maxi+1, -1); // 阻塞监听是否有客户端连接请求
		if (client[0].revents & POLLIN == POLLIN) // lfd有读事件
		{
			cfd = accept();
			for (int i = 1; i < OPEN_MAX; ++i)
			{
				if (client[i].fd < 0) // 找到空闲区域
				{
					client[i].fd = cfd; // 存放accept返回的cfd,添加到监听队列中
					break;
				}
			}
			// 监听刚刚返回的cfd的读事件
			client[i].events = POLLIN;
			// 更新最大元素下标
			if (i > maxi)
				maxi = i;
		}
		for (i = 1; i <= maxi; ++i) // 轮询所有的文件描述符
		{
			if (client[i].revents & POLLIN == POLLIN) // client[i]有读事件
				/*事务处理*/
		}
	}
	close(lfd);
	return 0;
}

Poll服务器实现demo

/* poll server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include <poll.h>
#include<iostream>
// #include "wrap.h"

using namespace std;

#define MAXLINE 1024
#define CLIENTSIZE 1024+1
#define SERV_PORT 2333
void perr_exit(const char* s){

    perror(s);
    exit(1);
}
int main(int argc, char *argv[])
{
    int listenfd ,connfd;

    struct pollfd client[CLIENTSIZE];

    char buff[MAXLINE];
    
   int maxi = 0;int index;

    char str[INET_ADDRSTRLEN]; /* #define INET_ADDRSTRLEN 16 */
   
    socklen_t cliaddr_len;
    
 
    int nready;
    //socket 1
    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    int opt = 1;
    // 设置套接字选项
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in servaddr, cliaddr;

    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    client[0].fd = listenfd;
    client[0].events = POLLIN;
    
    //socket 2
    int ret = bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    if(ret <0){perr_exit("bind error");}
    printf("ret: %d Server IP: %s Port %d create_socket: %d\n",ret, inet_ntoa(servaddr.sin_addr),ntohs(servaddr.sin_port),listenfd);

    //socket 3
    ret = listen(listenfd,40); 

    for (int i = 1; i < CLIENTSIZE; i++)
        client[i].fd = -1;

    while(1){
        nready = poll(client, maxi + 1, -1);
        if(nready <0)
            exit(-1);

        if((client[0].revents& POLLIN == POLLIN)){
            cliaddr_len = sizeof(cliaddr);

            //socket 4
            connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
            printf("received from %s at PORT %d\n",
                   inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
                   ntohs(cliaddr.sin_port));

            printf("connfd %d\n",connfd);
            //use map
             for (index = 1; index < CLIENTSIZE; index++)
             {
                 if (client[index].fd < 0)
                 {
                     client[index].fd = connfd;
                     client[index].events = POLLIN;
                     break;
                 }
             }
             

            /* 是否达到select能监控的文件个数上限 1024 */
            if (index == CLIENTSIZE) {
                fputs("too many clients\n", stderr);
                exit(1);
            }

            if(index > maxi)
                maxi = index;
                
            printf("maxi changed [%d]\n",maxi);
            if(--nready == 0)
                continue;
       
        } // client[0].revents& POLLIN  end

        
        int nlength;
        for(int i = 1;i <= maxi;i++){
            
            if( (client[i].fd)<0)
                continue;
            pollfd sockfd = client[i];

            if (sockfd.revents & POLLIN == POLLIN)
            {

                if ((nlength = read(sockfd.fd, buff, MAXLINE)) == 0)
                {
                    close(sockfd.fd);
                    client[i].fd = -1;
                    cout << "客户端关闭 " <<endl;
                }
                else if(nlength < 0){

                    //do something
                     // 收到RST标志
                    if (errno == ECONNRESET)
                    {
                        cout << "连接被重置" << endl;
                        close(sockfd.fd);
                        client[i].fd = -1; // poll不再监控该描述符
                    }
                    else
                        perr_exit("read");
                }
                else 
                {
                    for (int j = 0; j < nlength; j++)
                        buff[j] = toupper(buff[j]);

                    write(sockfd.fd, buff, nlength); // return client
                }
            }
            if(--nready == 0)
                break;
        }


    }
    close(listenfd);
    return 0;
}

参考
IO 多路复用之poll

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值