【网络编程】select和poll

select

select() 确定一个或多个套接口的状态,如:需要则等待。

#include <winsock.h>
int PASCAL FAR select( int nfds, fd_set FAR* readfds, fd_set FAR* writefds, fd_set FAR* exceptfds, const struct timeval FAR* timeout);

//参数说明:
- nfds:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。
- readfds:(可选)指针,指向一组等待可读性检查的套接口。
- writefds:(可选)指针,指向一组等待可写性检查的套接口。
- exceptfds:(可选)指针,指向一组等待错误检查的套接口。
- timeout:select()最多等待时间,对阻塞操作则为NULL

select(),确定一个或多个套接口的状态,本函数用于确定一个或多个套接口的状态,对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息,用fd_set结构来表示一组等待检查的套接口,在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目。有一组宏可用于对fd_set的操作,这些宏与Berkeley Unix软件中的兼容,但内部的表达是完全不同的。

//例子:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
using namespace std;

int main()
{
    int sock_listen=socket(AF_INET,SOCK_STREAM,0);

    int optval=1;
    setsockopt(sock_listen,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));

    sockaddr_in my_addr;
    my_addr.sin_family=AF_INET;
    my_addr.sin_addr.s_addr=INADDR_ANY;
    my_addr.sin_port=htons(8888);

    if(-1==bind(sock_listen,(sockaddr*)&my_addr,sizeof(my_addr)))
    {
        perror("bind()");
        return 0;
    }


    listen(sock_listen,5);

    int sock_conn=accept(sock_listen,NULL,NULL);

    int retval;
    char msg[1025];

    fd_set    rfds;//设置结构体

    while(1)
    {
//宏
        FD_ZERO(&rfds);
        FD_SET(0,&rfds);
        FD_SET(sock_conn,&rfds);//把套接字加入

        retval=select(sock_conn+1,&rfds,NULL,NULL,NULL);//开始

        if(retval<0)
        {
            perror("select()");
            break;
        }

        if(FD_ISSET(0,&rfds))
        {
            cin.getline(msg,sizeof(msg));
            send(sock_conn,msg,strlen(msg),0);
        }

        if(FD_ISSET(sock_conn,&rfds))
        {    
            retval=recv(sock_conn,msg,sizeof(msg)-1,0);    

            if(retval<=0)
            {
                cout<<"对方断开连接,通信结束!"<<endl;
                break;        
            }
            else
            {
                msg[retval]='\0';
                cout<<msg<<endl;
            }        
        }
    }

    close(sock_conn);

    close(sock_listen);

    return 0;
}


poll

poll()函数:这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,下面是这个函数的声明:


#include <poll.h>
int poll(struct pollfd fds[], nfds_t nfds, int timeout);

//参数说明:
- fds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符;

每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select()函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况;

//例子:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <poll.h>
using namespace std;

int main()
{
    int sock_listen=socket(AF_INET,SOCK_STREAM,0);

    int optval=1;
    setsockopt(sock_listen,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));

    sockaddr_in my_addr;
    my_addr.sin_family=AF_INET;
    my_addr.sin_addr.s_addr=INADDR_ANY;
    my_addr.sin_port=htons(8888);

    if(-1==bind(sock_listen,(sockaddr*)&my_addr,sizeof(my_addr)))
    {
        perror("bind()");
        return 0;
    }


    listen(sock_listen,5);

    int sock_conn=accept(sock_listen,NULL,NULL);

    int retval;
    char msg[1025];

    struct pollfd fds[2]={{0,POLLIN},{sock_conn,POLLIN}};

    while(1)
    {
        retval=poll(fds,2,-1);

        if(retval<0)
        {
            perror("poll()");
            break;
        }

        if(fds[0].revents)
        {
            cin.getline(msg,sizeof(msg));
            send(sock_conn,msg,strlen(msg),0);
        }

        if(fds[1].revents)
        {    
            retval=recv(sock_conn,msg,sizeof(msg)-1,0);    

            if(retval<=0)
            {
                cout<<"对方断开连接,通信结束!"<<endl;
                break;        
            }
            else
            {
                msg[retval]='\0';
                cout<<msg<<endl;
            }        
        }
    }

    close(sock_conn);

    close(sock_listen);

    return 0;
}

* 

posted @ 2024-10-28 10:35  快乐的提千万  阅读(1)  评论(0编辑  收藏  举报