对于select理解总结

来源:互联网 发布:淘宝宝贝排名在线查询 编辑:程序博客网 时间:2024/05/22 09:37

         select用途:在一段时间内,监听用户感兴趣的文件描述符上的可读可写和异常等时间。

         对于select函数的接口:

         int select(int nfds,fd_set* readfds,fd_set* writefds,fd_set* exceptfds,struct timeval* timeout);

         nfds表示监听的文件描述符总数,他是监听的最大值加1,目的是为了节省时间

         后面三个参数是可读可写和异常,最后一个参数是等待时间,如果给timeout变量的成员都传递0那么就立即返回,NULL就无限等待,若是一个struct timeval结构体,那么时间间就自己进行设定,具体的后续操作可以通过返回值来判定。

          fd_set是一个结构体,最多监听1024个,这是select的默认最大。

          关于select的返回值,如果超时切没有任何描述符就绪,那么返回0,如果失败则返回-1,如果成功那么就返回就绪文件描述符的总数,如果在等待期间接收到了信号那就返回-1。

         select对于接收带外数据也普通数据  都可使得select返回,但是select处于不同的就绪状态,前者可读,后者异常。

         关于select监听其他的进程给自己发送信息的代码如下:

#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>


int main()
{
  int sockfd = socket(AF_INET,SOCK_STREAM,0);
  assert(sockfd!=-1);


  struct sockaddr_in saddr,caddr;


  saddr.sin_family = AF_INET;
  saddr.sin_port = htons(6500);
  saddr.sin_addr.s_addr = inet_addr("192.168.1.11");


  int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
  assert(res!=-1);
  int ret = listen(sockfd,5);
  assert(ret!=-1);


  int len = sizeof(caddr);
  int c = accept(sockfd,(struct sockaddr*)&caddr,&len);//c已经在这里定义了所以只可以监控一个的,如果你想多个的可以自己修改


  fd_set rdset;


  while(1)
  {
       FD_ZERO(&rdset);//clear
       FD_SET(c,&rdset);//set read


       int n = select(c+1,&rdset,NULL,NULL,0);//always


       if(n<0)//error
       {
            break;
       }


        if(FD_ISSET(c,&rdset))
        {
          char buff[128] = {0};
          int ret =  recv(c,buff,127,0);
          if(ret <= 0)//如果客户端关闭,返回0直接退出
          {
               printf("client over!\n");
               break;
          }
          printf("%s",buff);
        }
}
  close(c);
  close(sockfd);
  return 0;


}

    相应的客户端代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int main(int argc,char *argv[])
{
   int sockfd = socket(AF_INET,SOCK_STREAM,0);
   assert(sockfd!=-1);


   struct sockaddr_in saddr;//虽然操作一样,但是客户端是为了去链接服务端
   memset(&saddr,0,sizeof(saddr));
   saddr.sin_family = AF_INET;
   saddr.sin_port = htons(6500);//转换成大端
   saddr.sin_addr.s_addr = inet_addr("192.168.1.11");
 //要用就必须先运行起来
   int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//链接到服务端上面
   assert(res!=-1);
   //执行到这个地方说明三次握手完成


   while(1)
   {
       printf("input:\n");
       char buff[128] = {0};


       fgets(buff,128,stdin);//fgets会用到空格回车
       if(strncmp(buff,"end",3)==0)
       {
           break;
       }


       send(sockfd,buff,strlen(buff),0);//把收到的讯息再发送出去
       memset(buff,0,128);
   }


   close(sockfd);//关闭
   return 0;
}

        个人总结,如果有不对的欢迎指正

         

0 0
原创粉丝点击