套接字编程---多路IO转接---poll实现代码

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <poll.h>

#define IP "127.0.0.1"
#define PORT 20000
#define CLIENT_SIZE 1024
#define BUFF_SIZE 1024

int main()
{
        int listenfd,connfd,sockfd;//listenfd用来accept新的连接, connfd作为accept的返回值,sockfd临时变量

        struct sockaddr_in servaddr,clieaddr;//服务器地址和客户端地址

        socklen_t clieaddrlen=sizeof(clieaddr);//客户端地址长度

        int ret;//临时变量

        struct pollfd client[CLIENT_SIZE];//poll函数使用的结构体数组

        int i,j,maxi;

        int nready;

        char buff[BUFF_SIZE];//字符缓存区

        char clientip[64];//存放客户端ip

        int num;

        listenfd=socket(PF_INET,SOCK_STREAM,0);//创建tcp套接字

        if(listenfd<0)
        {
                perror("socket error");
                exit(1);
        }

        //初始化服务器地址
        memset(&servaddr,'\0',sizeof(servaddr));
        servaddr.sin_family= AF_INET;
        servaddr.sin_port=htons(PORT);
        inet_pton(AF_INET,IP,&servaddr.sin_addr);

        ret=bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));//绑定服务器地址
        if(ret<0)
        {
                perror("bind error");
                exit(1);
        }

        ret=listen(listenfd,128);//监听新的连接
        if(ret<0)
        {
                perror("listen error");
                exit(1);
        }

        for(i=0;i<CLIENT_SIZE;i++)//初始化client结构体
        {
                client[i].fd=-1;
        }

        //将listenfd赋值给client[0]
        client[0].fd=listenfd;
        client[0].events=POLLIN;//读事件
        maxi=0;//始终指向client数组中最大的元素

        while(1)
        {
                nready = poll(client,maxi+1,-1);//使用poll函数将套接字的状态监听交给内核

                if(client[0].revents & POLLIN)//有新的连接请求
                {
                        memset(&clieaddr,'\0',sizeof(clieaddr));

                        connfd = accept(listenfd,(struct sockaddr *)&clieaddr,&clieaddrlen);

                        printf("An new connection was accepted. IP = %s, PORT = %d\n",
                                inet_ntop(AF_INET,&clieaddr.sin_addr,clientip,sizeof(buff)),
                                ntohs(clieaddr.sin_port));

                        for(i=0;i<CLIENT_SIZE;i++)
                        {
                                if(client[i].fd==-1)//将新的套接字赋值给client数组,并进行监听
                                {
                                        client[i].fd=connfd;
                                        client[i].events=POLLIN;

                                        if(maxi<i)
                                        {
                                                maxi=i;
                                        }

                                        break;
                                }
                        }

                        if(i==CLIENT_SIZE)//连接数超过了限制,关闭该连接
                        {
                                printf("too many clients, this connection will not be established.\n");

                                close(connfd);
                        }

                        if(--nready==0)//判断是否还有读事件满足
                        {
                                continue;
                        }

                }


                for(i=1;i<=maxi;i++)//逐个寻找满足读事件的各个套接字
                {
                        if((sockfd=client[i].fd)<0)
                        {
                                continue;
                        }

                        if(client[i].revents & POLLIN)
                        {
                                num = recv(sockfd,buff,sizeof(buff),0);

                                if(num<0)
                                {
                                        printf("recv error\n");
                                }
                                else if(num==0)
                                {
                                        close(sockfd);
                                        client[i].fd=-1;
                                        printf("An client disconnected.\n");
                                }
                                else
                                {
                                        for(j=0;j<num;j++)
                                        {
                                                buff[j]=toupper(buff[j]);
                                        }
                                        send(sockfd,buff,num,0);
                                }
                                if(--nready==0)
                                {
                                        break;
                                }

                        }

                }
        }
}

运行效果:

[zlf@rhel5 day20181226]$ ./server
An new connection was accepted. IP = 127.0.0.1, PORT = 50031
An new connection was accepted. IP = 127.0.0.1, PORT = 50032
An client disconnected.
An new connection was accepted. IP = 127.0.0.1, PORT = 50033
An new connection was accepted. IP = 127.0.0.1, PORT = 50034
An client disconnected.
An client disconnected.
An client disconnected.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

历史五千年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值