代码纯享:linux下poll实现简单的回射服务器

    简介:客户端连接服务器,向服务器发送什么内容,服务器就回客户端什么内容。IP可改。

#include <stdio.h>                                                                                                                              
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <poll.h>
#define PORT 9000
#define FWQIP 0 //IP端口,可改
int main(int argc, char* argv[])
{
    int lfd=socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in seraddr,cliaddr;
    seraddr.sin_family=AF_INET;
    seraddr.sin_port=htons(PORT);
    seraddr.sin_addr.s_addr=FWQIP;
    int a=bind(lfd,(struct sockaddr*)&seraddr,sizeof(seraddr));
    if(a<0)
    {
         perror("bind error:");
         return 0;
    }
   listen(lfd,64);
   socklen_t len=sizeof(cliaddr);
    //定义一个结构体数组
   struct pollfd fds[1025];//定义了1025个结构体数组,他比select优势在于他的个数可以由结构体指定,而不是像select一样固定的1024个
   int i=0;
   for(i=0; i<1025;i++)
   {
       fds[i].fd=-1;//全部赋值为-1是为了后面好操作。
   }
   fds[0].fd=lfd;//监听lfd文件描述符
   fds[0].events=POLLIN;
   int maxfd=0;//在结构体数组中的目前最大下标是0.
   while(1)
   {
       int pollnum= poll(fds, maxfd+1 , -1);//-1表示一直等待,如果没有事件发生他不会返回直接执行下面的语句。fds表示结构体数组
       if(pollnum < 0)
       {
           perror("accpet error:");
           // exit(1);
       }
       else//poll没有出错,监听有没有新的客户机和我连接
       {
           if(fds[0].revents & POLLIN)//判断lfd的POLLIN事件有没有发生,用&,判断是因为如果不仅仅是POLLIN事件发生了那么用==判断就会出错,这里只>
           //没有就执行for语句的数据处理,不加该判断会导致,没有新的连接时阻塞在accept上
           {
               int  cfd=accept(lfd,(struct sockaddr*)&cliaddr,&len);
               if(cfd < 0)//表示accept出错
               {
                   perror("accept error:");
                   // exit(1);
               }
               else
               {
                   //accept没有出错,解析客户机的IP和端口号
                   int cliport=ntohs(cliaddr.sin_port);//网络端口号转本地端口号
                   char det[1025];
                   inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, det,sizeof(det));//网络IP转本地IP
                   printf("客户端已连接:IP = %s  , 端口号 = %d\n", det , cliport);
                   //我们要把accept返回的文件描述符即与客户机通信的描述符重新加回到监听行列中
                   for(i= 1;i < 1025; i++)
                   {
                       if(fds[i].fd==-1)//前面初始化时候全部赋值为-1就是为了这里好找到空闲的
                       {
                           fds[i].fd=cfd;
                           fds[i].events=POLLIN;
                           break;
                       }
                       // if(--pollnum ==0 )//表示全部加到监听结构体里面了
                       // {
                       //   break;
                       // }为什么不能把这个if语句写在for里面,假如同时间有n个客户机连接我。但是accept一次只能从全连接队列里面取一个出来,你写在for里面看似把所有的客户机的描述符都放进来结构体数组里面,其实结构体数组里面有多个重复的fds[].fd
                   }
                   //修改maxfd的值
                   if(maxfd < i)
                   {
                       maxfd = i;
                   }
                   if(--pollnum == 0)
                   {
                       continue;
                   }
               }
           }
           //lfd处理完了,现在可以对客户机发送的数据进行处理了。
           for( i=1 ; i < maxfd+1; i++)//通过循环的方式,一个一个的去判断POLLIN事件有没有发生
           {
               if(fds[i].revents & POLLIN)//判断POLLIN事件有没有发生
               {
                   char buf[1024];
                   int rr=read(fds[i].fd, buf,sizeof(buf));
                   if(rr==0)
                   {
                       printf("客户端断开连接\n");
                       close(fds[i].fd);
                       fds[i].fd=-1;
                   }
                  if(rr<0)
                  {
                      perror("read error:");
                      exit(1);
                  }
                  write(1, buf, rr);
                  write(fds[i].fd, buf, rr);
                  if(--pollnum==0)//要么不写这个,要么只能写if(fds[i].revents & POLLIN)的里面
                  {
                      break;
                  }
              }
                 //if(--pollnum==0)
                 //{
                   //  break;
                //}//为什么不能把这个if语句写外面,假如现在只有一个客户端发送了数据,但是这个客户端的描述符可能不是1。但是你每一次都执行了--pollunm就导致了都没有判断到客户端的cfd触发没有呢就break了
           }
       }
   }
   return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值