多路复用-select

现实中我们写的很多网络通信的程序都不可能是一对一的,很多时候需要来实现一个并发的服务器来满足更多用户的接入,而对于并发的实现也有好几种方式,多线程、多进程、多路复用
多路复用
对于多路复用这种方式也有好几种实现方式:poll、epoll、select,虽然用起来有一些不同的细节,不过都大同小异,在我的程序中使用的是select.
先说一下我的需求,其实我只有一个sockfd文件描述符,只是一个udp通信的socket描述符,所以我这里并不是一个并发程序,我使用select机制只是为了使用其中的延时检测,服务器等待指定的时间,程序框架如下
client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
typedef struct sockaddr* saddrp;
int main(int argc, char const *argv[])
{
     int sockfd = socket(AF_INET,SOCK_DGRAM,0);
     if (0 > sockfd)
     {
          perror("socket");
          return -1;
     }
     struct sockaddr_in addr = {};
     addr.sin_family = AF_INET;
     addr.sin_port = htons(5577);
     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
     socklen_t addr_len = sizeof(struct sockaddr_in);
     while(1)
     {
        char buf[255] = {};
        printf("Please input the return value:");
        fgets(buf,255,stdin);
        buf[strlen(buf) - 1] = '\0';
        sendto(sockfd,buf,strlen(buf)+1,0,(saddrp)&addr,addr_len);
        if (0 == strcmp(buf,"q")) break;
     }
     close(sockfd);
     return 0;
    }

客户端就是一个普通的UDP client程序
server.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/time.h>
#include <arpa/inet.h>
typedef struct sockaddr* saddrp;
int main(int argc, char const *argv[])
{
        //创建socket
        int sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if (0 > sockfd)
        {
                perror("sockfd");
                return -1;
        }
         //准备地址
        struct sockaddr_in addr = {};
        addr.sin_family = AF_INET;//ipv4
        addr.sin_port = htons(5577);//端口号
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");//我的ip地址
        socklen_t addr_len = sizeof(struct sockaddr_in);		
         //绑定
        int ret = bind(sockfd,(saddrp)&addr,sizeof(addr));
        if (0 > ret)
        {
                perror("bind");
                return -1;
        }
        /* 超时变量 */
        struct timeval tv;
        fd_set fdsr;
        while(1) {
                FD_ZERO(&fdsr);
                FD_SET(sockfd,&fdsr);
                /* 30S等待 */
                tv.tv_sec = 30;
                tv.tv_usec =0;
                /* 监控描述符是sockfd,所以这里最大的个数应该是socket+1,太小的话检测不到 */      	
                int ret = select(sockfd+1, &fdsr, NULL, NULL, &tv);
                switch(ret)
                {
                        case 0:
                                printf("select time out ......\n");
                                break;
                        case -1:
                                perror("select");
                                break;
                        default:
                                if(FD_ISSET(sockfd, &fdsr)) {
                                        char buf[128] = {0};
                                      recvfrom(sockfd,buf,sizeof(buf),0,(saddrp)&addr,&addr_len);
                                      rintf("Recv:%s\n",buf);
                                }
                                break;
                }
        }
        close(sockfd);
        return 0;
}

将udp server的socket描述符加入select等到,设置的超时时间是30S,如果接收到消息就会执行default部分,打印消息,
结果:超时检测
在这里插入图片描述
消息检测
在这里插入图片描述

发布了33 篇原创文章 · 获赞 2 · 访问量 1030

猜你喜欢

转载自blog.csdn.net/weixin_41791581/article/details/102960917