高性能服务器之select

系统提供select函数来实现多路复⽤用输⼊入/输出模型。select系统调⽤用是⽤用来让我们的程序监视 多个⽂文件句柄的状态变化的。程序会停在select这⾥里等待,直到被监视的⽂文件句柄有⼀一个或 多个发⽣生了状态改变
int select(int nfds,fd_set * readfds,fd_set*writefds,fd_set*exceptfds,struct timeval*timeout)
(1)参数nfds是需要监视的最⼤大的⽂文件描述符值+1; (2)rdset,wrset,exset分别对应于需要检测的可读⽂文件描述符的集合,可写⽂文件描述符的集 合及异 常⽂文件描述符的集合。 struct timeval结构⽤用于描述⼀一段时间长度,如果在这个时间内,需要监视的描述符没有事件 发⽣生则函数返回,返回值为0。 下⾯面的宏提供了处理这三种描述词组的⽅方式: FD_CLR(inr fd,fd_set* set);⽤用来清除描述词组set中相关fd 的位 FD_ISSET(int fd,fd_set *set);⽤用来测试描述词组set中相关fd 的位是否为真 FD_SET(int fd,fd_set*set);⽤用来设置描述词组set中相关fd的位 FD_ZERO(fd_set *set);⽤用来清除描述词组set的全部位 参数timeout为结构timeval,⽤用来设置select()的等待时间,其结构定义如下
struct timeval{
long tv_sec;
long tv_usec;
}
(3)如果参数timeout设为: NULL:则表⽰示select()没有timeout,select将⼀一直被阻塞,直到某个⽂文件描述符上发⽣生了 事件。 0:仅检测描述符集合的状态,然后⽴立即返回,并不等待外部事件的发⽣生。 特定的时间值:如果在指定的时间段⾥里没有事件发⽣生,select将超时返回。 函数返回值: 执⾏行成功则返回⽂文件描述词状态已改变的个数 如果返回0代表在描述词状态改变前已超过timeout时间,没有返回; 当有错误发⽣生时则返回-1,错误原因存于errno,此时参数readfds,writefds,exceptfds和 timeout的值变成不可预测。错误值可能为: EBADF ⽂文件描述词为⽆无效的或该⽂文件已关闭 EINTR 此调⽤用被信号所中断 EINVAL 参数n 为负值。 ENOMEM 核⼼心内存不⾜
3,代码:
服务器端:

#include<stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include<sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string.h>
#include<stdlib.h>
int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        printf("Usage: %s[server_ip][server_port]\n",argv[0]);
       exit(1);
    }
    int sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("socket");
        exit(2);
    }
    struct sockaddr_in server;
    server.sin_family=AF_INET;
    server.sin_port=htons(atoi(argv[2]));
    server.sin_addr.s_addr=inet_addr(argv[1]);
    int c=connect(sock,(struct sockaddr*)&server,sizeof(server));
    if(c>0)
    {
        printf("please Enter#");
        fflush(stdout);
        dup2(1,sock);
        printf("server Echo#");
        dup2(sock,1);
    }
    return 0;
}

服务器端

#include<stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include<sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string.h>
#include<stdlib.h>

int StatUp(char*ip,int port)
{
    int sock=socket(AF_INET, SOCK_STREAM, 0);
    if(sock<0)
    {
        perror("socket");
        exit(2);
    }
    struct sockaddr_in local;
    local.sin_addr.s_addr=inet_addr(ip);
    local.sin_port=htons(port);
    socklen_t len=sizeof(local);
   int b=bind(sock,(struct sockaddr*)&local,len);
   if(b<0)
    {
       perror("bind");
       exit(3);
    }
  int l=listen(sock,10);
  if(l<0)
    {
      perror("listen");
      exit(4);
     }
   return sock;
}

int main(int argc,char* argv[])
{
    int newfile=open("./test1",O_CREAT|O_RDWR,0666);
    if(argc!=3)
    {
        printf("Usger:%s [server_ip][server_port]",argv[0]);
        exit(1);    
    }
    int listen_sock=StatUp(argv[1],atoi(argv[2]));
    int r_arr[10];
    int i;
    for(i=0;i<10;i++)
    {
        r_arr[i]=-1;     
    }
    fd_set rfds;
    r_arr[0]=listen_sock;
        while(1)
        {
            FD_ZERO(&rfds);
            int max_fd=-1;
           struct timeval timeout={5,0};
        for(i=0;i<10;i++)
            {
              if(r_arr[i]>0)
              { 
                  FD_SET(r_arr[i],&rfds);
                  if(max_fd<r_arr[i])
                      max_fd=r_arr[i];
              }
            }
       switch( select(max_fd+1,&rfds,NULL,NULL,NULL))
       {
        case 0:
               printf("time out\n");
               break;
        case -1:
               perror("select");
               break;
        default:
           {
               int j,k;
               struct sockaddr_in  client;
               socklen_t len=sizeof(client);
               for( j=0;j<10;j++)
               {
                  if(j==0 && FD_ISSET(r_arr[j],&rfds))
                 {
                    int newsock=accept(listen_sock,(struct sockaddr*)&client,&len);
                 if(newsock>0)
                   {
                       printf("get client\n");
                     for(i=0;i<10;i++)
                     {  
                         if(r_arr[i]<0)
                          {
                            r_arr[i]=newsock;
                            break;
                          } 
                    }
                    if(i==10)
                        close(newsock);
                  }//accept success
                else                    
                {               
                    perror("accept");                       
                     continue;
                } //accept false
               } //is listen    
               else if(j>0 && FD_ISSET(r_arr[j],&rfds))
               {  
                    char buf[1024];
                    int s=read(r_arr[j],buf,sizeof(buf)-1);
                    if(s==0)
                    {                   
                        printf("file is close");
                        fflush(stdout);
                        close(r_arr[j]);
                        r_arr[j]=-1;                
                    }
                    else if(s>0)
                    {                   
                        buf[s-1]=0;
 //                     fflush(stdout);
                        printf("read file:%s\n",buf);
                        fflush(stdout);
                    }
                    else
                    {                   
                        perror("read");
                        break;
                    }
                }//isn"t listen sock
           }//for j
          // int k;
       for(k=0;k<10;k++)   //resolve write
       {
           if(w_arr[k]<0)
               continue;
               char * p="I'am server! hello";
           if(FD_ISSET(w_arr[k],&wfds))
           {
               write(w_arr[k],p,strlen(p));
               close(w_arr[k]);
               w_arr[k]=-1;   
           }
       }  //for k
        }//default
           break;
       }//swith
    }//while
          return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值