• 多路复用select


    多路复用I/O:一个执行体监视多个文件描述符对象的状态是否改变,一旦改变通知其他执行体来实现。

    基本思想:

    1、 先构造一张有关描述符的表,然后调用一个函数,当这些文件描述符中的一个或者多个已准备好进行I/O时函数才返回

    2、 函数返回时告诉进程那个描述符已准备就绪,可以进行I/O操作。

    Select(int n,fd_set *read_fds,fd_set *write_fds,fd_set *except_fds,struct timeval *timeout);

    注意两点:

    1、 select函数返回之前会将集合中状态未改变的fd清除

    2、 返回值为状态改变的文件描述符对象的个数。

    3、 Select阻塞时内部会产生一个线程盯着描述符对象的状态改变。

    参数:n:maxfd,所有监控的文件描述符中值最大的加1

    Read_fds:是否可读的文件描述符集

    Write_fds:是否可写的文件描述符集

    Except_fds:出错的文件描述符集

    Timeout:如果设置为NULL,则会一直阻塞,直到文件描述符的状态改变

    Struct timeval

    {

    Long tv_sec;

    Long tv_usec;

    } ;

    文件描述符的几个宏:

    FD_ZERO(fd_set *fdset):清空文件描述符集

    FD_SET(int fd,fd_set *fdset):fd加入到fd_set集中

    FD_ISSET(int fd,fd_set*fdset):判断fd是否在fdset

    FD_CLR(fd,fd_set *fdset);fdfdset集中清除

    Select函数使用范例(功能:本例使用的是tcpselect监听标准输入是否准备好字符串可读然后发送和socketfd是否可读,然后接受,实现以简单的qq通信)

    客户端:
    #include<stdio.h>
    #include<pthread.h>
    #include<netinet/in.h>
    #include<stdlib.h>
    #include<string.h>
    #include<strings.h>
    #include<sys/types.h>
    #include<sys/socket.h>
    int main()
    {
        int socketfd,ret;
        fd_set fd;
        FD_ZERO(&fd);
        FD_SET(0,&fd);
            
        
        socketfd = socket(PF_INET,SOCK_STREAM,0);
        FD_SET(socketfd,&fd);
        ret = select(socketfd+1,&fd,NULL,NULL,NULL);
        struct sockaddr_in saddr;
        memset(&saddr,0,sizeof(saddr));
        saddr.sin_family = PF_INET;
        saddr.sin_port = htons(6000);
        saddr.sin_addr.s_addr = inet_addr("192.168.1.46");
        
        if(connect(socketfd,(struct sockaddr *)&saddr,sizeof(struct sockaddr))<0)
    
            perror("connect() error!
    ");
        char buf[20],buf1[20];
        while(1)
        {
            bzero(buf,20);
            bzero(buf1,20);
            
        FD_SET(0,&fd);
        FD_SET(socketfd,&fd);
        ret = select(socketfd+1,&fd,NULL,NULL,NULL);
                if(FD_ISSET(socketfd,&fd))
                {
                if(recv(socketfd,buf1,sizeof(buf1),0)<0)
                    perror("recv() error!
    ");
                    printf("%s",buf1);
                    continue;
                }
                if(FD_ISSET(0,&fd))
                {
    //            printf("please input:
    ");
                fgets(buf,20,stdin);    
                if(send(socketfd,buf,strlen(buf),0)<0)
                perror("send() error!
    ");
                continue;
                }    
    
            }
    }    
    服务器端:
    #include<stdio.h>
    #include<netinet/in.h>
    #include<stdlib.h>
    #include<string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include<pthread.h>
    #include<strings.h>
    int main()
    {
        int fds[12];
        int maxfd = -1;
        int socketfd = socket(PF_INET,SOCK_STREAM,0);
        if(socketfd<maxfd)
            maxfd = socketfd;
        struct sockaddr_in saddr;
        memset(&saddr,0,sizeof(saddr));
        saddr.sin_family = PF_INET;
        saddr.sin_port = htons(6000);
        saddr.sin_addr.s_addr = inet_addr("192.168.193.2");
        int newsocketfd;
        int n = 1;
        setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(int));
        if(bind(socketfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr_in))<0)
            perror("bind() error!
    ");
        
        if(listen(socketfd,5)<0)
            perror("listen() error!
    ");
        struct sockaddr_in caddr;
        int s = sizeof(struct sockaddr);
        newsocketfd=accept(socketfd,(struct sockaddr*)&caddr,&s);
        fd_set fd;
        FD_ZERO(&fd);
        int ret;
        char buf[20],buf1[20];
        int i;
        int rsize;
                printf("hello
    ");
        while(1)
        {    
            bzero(buf,20);
            bzero(buf1,20);
    //            printf("hello
    ");
            FD_SET(0,&fd);    
    //            printf("hello
    ");
            FD_SET(newsocketfd,&fd);
    //            printf("hello
    ");
        select(newsocketfd+1,&fd,NULL,NULL,NULL);
            if(FD_ISSET(newsocketfd,&fd))
                {
    //            printf("hello
    ");
                if(recv(newsocketfd,buf1,sizeof(buf1),0)<0)
                perror("recv() error!
    ");
                printf("%s",buf1);
    //            printf("hello
    ");
                continue;
                }
            
                if(FD_ISSET(0,&fd))
                {
                fgets(buf,20,stdin);    
                if(send(newsocketfd,buf,strlen(buf),0)<0)
                perror("send() error!
    ");
                continue;
                }
        }
        close(socketfd);
        close(newsocketfd);
    
    }
  • 相关阅读:
    git 常用命令 command 1.0(本地 local repository 对远程仓库 remote repository 的操作)
    git 常用命令 command
    git .gitignore 忽略列表
    节点的类型
    Error.name 六种值对应的信息
    js或jquery中的验证
    转载:JavaWeb学习总结(五十三)——Web应用中使用JavaMail发送邮件
    转载:JavaWeb学习总结(五十二)——使用JavaMail创建邮件和发送邮件
    转载:JavaWeb学习总结(五十一)——邮件的发送与接收原理
    转载:JavaWeb学习总结(五十)——文件上传和下载
  • 原文地址:https://www.cnblogs.com/defen/p/5287647.html
Copyright © 2020-2023  润新知