多路复用poll和域套接字

多路复用poll

#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
参数
    fds:要监控文件描述符集合
        struct pollfd {
            int   fd;         /* file descriptor */
            short events;     /* requested events */
            short revents;    /* returned events */
        };
		events和revents:
            POLLIN 有数据可读
            POLLOUT写数据
            POLLER指定文件描述符发生错误
            POLLRDHUP判断tcp的socket关闭了连接
            		加上一个宏 _GNU_SOURCE 
            		#define _GNU_SOURCE 1
            		#include <poll.h>
    nfds:监控多少个文件描述符
    timeout:超时(毫秒)
            > 0等待的时间
            ==0非阻塞
            < 0阻塞 INFTIM
   返回值:
         成功,返回结构体revents域不为0的文件描述符个数
         失败,-1
         如果超时返回0
  1 /*================================================================
  2  *   Copyright (C) 2020 hqyj Ltd. All rights reserved.
  3  *   
  4  *   文件名称:02_多路复用01.c
  5  *   创 建 者:Chens
  6  *   创建日期:2020年04月24日
  7  *   描    述:执行的时候需要加sudo
  8  *
  9  ================================================================*/
 10  
 11  
 12 #include <stdio.h>
 13 #include <sys/time.h>
 14 #include <sys/types.h>
 15 #include <unistd.h>
 16 #include <sys/types.h>
 17 #include <sys/stat.h>
 18 #include <fcntl.h>
 19 #include <stdlib.h>
 20 #include <poll.h>
 21  
 22 int main(int argc, char *argv[])
 23 {
 24     //打开鼠标驱动文件
 25     int fd =-1;
 26     fd = open("/dev/input/mouse0",O_RDONLY);
 27     if(fd < 0){
 28         perror("open");
 29         exit(1);
 30     }
 31  
 32     //1,创建文件描述符集合
 33     struct pollfd fds[2];
 34     //2,把关心的文件描述符填入
 35     fds[0].fd = 0;//监控键盘
 36     fds[0].events = POLLIN;//监控键盘的输入
 37  
 38     fds[1].fd = fd;//监控鼠标
 39     fds[1].events = POLLIN;//监控鼠标输入
 40  
 41  
 42     int val =-1;
 43  
 44     while(1){
 45  
 46         val = poll(fds,2,1000);
 47         if(val <0){
 48             perror("poll");
 49             exit(1);
 50         }
 51         else if(0 == val){
 52             puts("-------超时了");
 53             continue;
 54         }
 55         else{
 56             if(fds[0].revents == POLLIN){
 57                 puts("键盘输入++++++++");
 58             }
 59             if(fds[1].revents == POLLIN){
 60                 puts("****鼠标动了***");
 61             }
 62         }
 63     }
 64     close(fd);
 65     return 0;
 66 }                                                                   

2、域套接字

​ 用于本地间通讯,域套接字 易用性、效率还可以不错

#include <sys/socket.h>
#include <sys/un.h>

unix_socket = socket(AF_UNIX, type, 0);

socket(AF_LOCAL,SOCK_STREAM,0);
socket(AF_LOCAL,SOCK_DGRAM ,0);

struct sockaddr_un {
    sa_family_t sun_family;    填写AF_UNIX
    char        sun_path[108]; 套接字文件绝对路径
    这个套接字必须事先不存在
};

填充结构体
    struct sockaddr_un myaddr;
	bzero(&myaddr.sizeof(myaddr));
	myaddr.sun_family = AF_UNIX;
	strcpy(myaddr.sun_path,"/tmp/mysocket");

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LIUgZ7MG-1587912699172)(.\1.png)]

#include <unistd.h>
int access(const char *pathname, int mode);
参数:
    pathname路径文件名
    mode:
    	F_OK判断存在
    	X_OK判断权限执行权限
    	W_OK判断权限写权限
    	R_OK判断权限读权限
    返回值:
    	成功0失败-1
#include <unistd.h>
int unlink(const char *pathname);
返回值,成功0,失败-1
  1 /*================================================================
  2  *   Copyright (C) 2020 hqyj Ltd. All rights reserved.
  3  *               
  4  *   文件名称:01_域套接字服务器.c
  5  *   创 建 者:Chens
  6  *   创建日期:2020年04月26日
  7  *   描    述:  
  8  *               
  9  ================================================================*/
 10                  
 11                  
 12 #include <stdio.h>
 13 #include <stdint.h>
 14 #include <sys/types.h>
 15 #include <sys/socket.h>
 16 #include <stdlib.h>
 17 #include <unistd.h>
 18 #include <arpa/inet.h>
 19 #include <string.h>
 20 #include <errno.h>
 21 #include <sys/socket.h>
 22 #include <sys/types.h>
 23 #include <sys/wait.h>
 24 #include <sys/un.h>
 25                  
 26 #define  QUIT         "quit"
 27 #define BACKLOG       10
 28 #define PATH          "/tmp/20021/unix_sock"
 29                  
 30                  
 31 int main(int argc, char *argv[])
 32 {                
 33     int sockfd = -1;
 34     sockfd = socket(AF_LOCAL,SOCK_STREAM,0);
 35                  
 36     int b_reuse = 1;
 37     setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
 38                  
 39     struct sockaddr_un sun;
 40     bzero(&sun,sizeof(sun));
 41     sun.sun_family    = AF_LOCAL;
 42     strncpy(sun.sun_path,PATH,strlen(PATH));
 43                  
 44     if(!access(PATH,F_OK))unlink(PATH);
 45                  
 46     if(bind(sockfd,(struct sockaddr*)&sun,sizeof(sun))<0){
 47         perror("bind");
 48         exit(1); 
 49     }            
 50                  
 51     if(listen(sockfd,BACKLOG)<0){
 52         perror("listen");
 53         exit(1); 
 54     }            
 55                  
 56                  
 57     char buf[BUFSIZ]={};
 58                  
 59     //创建集合   
 60     fd_set readfds,temp;
 61     //初始化集合(清空集合)
 62     FD_ZERO(&readfds);
 63     FD_ZERO(&temp);
 64     //把关心的文件描述符加入集合
 65     FD_SET(0,&readfds);
 66     FD_SET(sockfd,&readfds);
 67                  
 68     puts("IO多路复用服务器就绪");
 69     int maxfd = sockfd;
 70     int val = -1;                                                            
 71     int i = -1;  
 72     ssize_t recv_t = -1;
 73                  
 74     int setfd = -1;
 75     int input_t = -1;
 76     int ret = -1;
 77     int acceptfd = -1;
 78     puts("输入方式:“客户端对应的文件描述符 内容");
 79     while(1){    
 80         temp = readfds;
 81         val = select(maxfd+1,&temp,NULL,NULL,NULL);
 82         if(val<0){
 83             perror("select");
 84             exit(1);
 85         }        
 86         //轮训判断那个文件描述符产生事件
 87         for(i=0;i<maxfd+1;i++){
 88             if(FD_ISSET(i,&temp)){
 89                 if(0==i){//是键盘输入产生事件
 90                     bzero(buf,sizeof(buf));
 91                     input_t = scanf("%d %s",&setfd,buf);
 92                     while(getchar()!='\n');
 93                     if(input_t !=2){
 94                         puts("输入错误!请按格式输入:fd+空格+消息内容");
 95                         continue;
 96                     }
 97                     if(!FD_ISSET(setfd,&readfds)){
 98                         puts("输入fd号错误,没有这个链接!");
 99                         continue;
100                     }
101                     //发出信息
102                     do{
103                         ret = send(setfd,buf,strlen(buf),0);
104                     }while(ret<0 && EINTR==errno);
105                 }
106                 //如果是socket产生的套接字文件描述符
107                 //那就说明是要建立连接
108                 else if(sockfd == i){
109                     acceptfd = accept(sockfd,NULL,NULL);
110                     if(acceptfd < 0){
111                         perror("accept");
112                         exit(1);
113                     }
114                     //newfd加入集合
115                     FD_SET(acceptfd,&readfds);
116                     //更新maxfd(判断那个最大的文件描述符是那个)
117                     maxfd = (maxfd > acceptfd) ? maxfd : acceptfd;
118                 }
119                 else//剩下的情况就是所有的客户端对应的newfd了
120                 {
121                     bzero(buf,sizeof(buf));
122                     //i就是产生事件的客户端对应的fd
123                     //接收消息
124                     do{
125                         recv_t = recv(i,buf,sizeof(buf),0);
126                     }while(recv_t < 0 && EINTR==errno);
127                     if(recv_t <= 0){
128                         perror("客户端错误或关闭");
129                         FD_CLR(i,&readfds);
130                         close(i);
131                         maxfd = (( i == maxfd) ? (--maxfd) : maxfd);
132                     }
133                     else{
134                         printf("收到%d 消息:%s\n",i,buf);
135                     }
136                 }
137             }    
138         }        
139     }            
140                  
141     close(sockfd);
142                  
143     return 0;    
144 }                

  1 /*================================================================
  2  *   Copyright (C) 2020 hqyj Ltd. All rights reserved.
  3  *                                          
  4  *   文件名称:02_域套接字客户端.c          
  5  *   创 建 者:Chens                        
  6  *   创建日期:2020年04月26日               
  7  *   描    述:                             
  8  *                                          
  9  ================================================================*/
 10                                             
 11                                             
 12 #include <stdio.h>                          
 13 #include <stdint.h>                         
 14 #include <sys/types.h>                      
 15 #include <sys/socket.h>                     
 16 #include <stdlib.h>                         
 17 #include <unistd.h>                         
 18 #include <arpa/inet.h>                      
 19 #include <string.h>                         
 20 #include <errno.h>                          
 21 #include <sys/socket.h>                     
 22 #include <sys/types.h>                      
 23 #include <sys/wait.h>                       
 24 #include <sys/un.h>                         
 25                                             
 26 #define  QUIT         "quit"                
 27 #define BACKLOG       10                    
 28 #define PATH          "/tmp/20021/unix_sock"
 29                                             
 30                                             
 31 int main(int argc, char *argv[])            
 32 {                                           
 33     int fd = -1;                            
 34     fd = socket(AF_LOCAL,SOCK_STREAM,0);    
 35                                             
 36     struct sockaddr_un sun;                 
 37     bzero(&sun,sizeof(sun));                
 38     sun.sun_family    = AF_LOCAL;           
 39     strncpy(sun.sun_path,PATH,strlen(PATH));                              
 40                                             
 41     if(access(PATH,F_OK|W_OK) <0){          
 42         puts("路径文件不存在或没有权限");   
 43         exit(1);                            
 44     }                                       
 45                                             
 46     if( connect(fd,(struct sockaddr*)&sun,sizeof(sun))<0){
 47         perror("connect");                  
 48         exit(1);                            
 49     }                                       
 50                                             
 51     puts("域套接字客户端OK!");             
 52                                             
 53                                             
 54     int ret =-1;                            
 55     int fh =-1;                             
 56     fd_set readfds;                         
 57     int maxfd =-1;                          
 58     struct timeval tv={1,0};                
 59     char buf[BUFSIZ]={};                    
 60                                             
 61     puts("准备就绪-----------");            
 62     while(1){                               
 63         FD_ZERO(&readfds);                  
 64         FD_SET(0,&readfds);                 
 65         FD_SET(fd,&readfds);                
 66         tv.tv_sec = 5;                      
 67         tv.tv_usec= 0;                      
 68         maxfd = fd;                         
 69         fh = select(maxfd+1,&readfds,NULL,NULL,&tv);
 70         if(fh<0){                           
 71             perror("select");               
 72             exit(1);                        
 73         }                                   
 74         if(FD_ISSET(0,&readfds)){//键盘输入了
 75             bzero(buf,BUFSIZ);              
 76             do{                             
 77                 ret = read(0,buf,BUFSIZ-1); 
 78             }while(ret<0&&EINTR==errno);    
 79             if(ret <0){                     
 80                 perror("read");             
 81                 continue;                   
 82             }                               
 83             if(!ret)continue;               
 84             if(write(fd,buf,strlen(buf))<0){
 85                 perror("write");            
 86                 exit(1);                    
 87             }                               
 88             if(!strncasecmp(buf,QUIT,strlen(QUIT))){
 89                 printf("***客户端退出***\n");
 90                 break;                      
 91             }                               
 92         }                                   
 93         if(FD_ISSET(fd,&readfds)){//接收数据
 94             bzero(buf,BUFSIZ);              
 95             do{                             
 96                 ret = read(fd,buf,BUFSIZ-1);
 97             }while(ret<0 && EINTR==errno);  
 98             if(ret<0){                      
 99                 perror("接收");             
100                 continue;                   
101             }                               
102             if(!ret)break;                  
103             printf("已收到:%s \n",buf);    
104         }                                   
105     }                                       
106     close(fd);                              
107                                             
108     return 0;                               
109 }                                           

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值