select监听多个socket的例子

来源:互联网 发布:网络女直播 编辑:程序博客网 时间:2024/05/16 06:22

         先贴上代码,回头再仔细编辑。

         server.cpp:

#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <stdlib.h>#include <assert.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <vector>using namespace std;int main(int argc,char* argv[]){    printf("server start up\n");    if(argc <= 3)    {        printf("usage:%s ip port backlog\n",basename(argv[0]));        return 1;    }    //IP地址    const char* ip = argv[1];    //端口号    int port = atoi(argv[2]);    //内核监听队列的最大长度(完全连接的socket)    int backlog = atoi(argv[3]);    //创建socket(TIP/IP协议族,流式socket)    int server_sockfd = socket(PF_INET,SOCK_STREAM,0);    //最大连接数,初始化为server_sockfd    int max_fd = server_sockfd;    //    vector<int> connFds;    connFds.reserve(backlog);    //TCP/IP协议族的socket地址结构体    struct sockaddr_in server_addr;    bzero(&server_addr,sizeof(server_addr));    server_addr.sin_family = AF_INET;//TCP/IPv4的地址族    inet_pton(AF_INET,ip,&server_addr.sin_addr);//将IP地址字符串转换为二进制的整数并赋给addr.sin_server_addr    server_addr.sin_port = htons(port);//端口,host to net,将主机字节序(小端)转换为网络字节序(大端)    //将文件描述符sock和socket地址关联,仅服务端需要,客户端自动绑定地址    //注意需要强制转换为 struct sockaddr*    int ret = bind(server_sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));    assert(ret != -1);    //监听    ret = listen(server_sockfd,backlog);    assert(ret != -1);    //客户端地址信息    struct sockaddr_in client_addr;    socklen_t client_addrlength = sizeof(client_addr);    char buf[1024];    memset(buf,0,sizeof(buf));        //文件描述符集合    fd_set read_fds;    fd_set  exception_fds;    FD_ZERO(&read_fds);    FD_ZERO(&exception_fds);        //超时    struct timeval timeout;    timeout.tv_sec = 30;             //妙    timeout.tv_usec = 0 ;            //微秒    while(1)    {        FD_SET(server_sockfd,&read_fds);        for(int i =0;i<connFds.size();++i)        {            FD_SET(connFds[i],&read_fds);            FD_SET(connFds[i],&exception_fds);        }        int ret = select(max_fd+1,&read_fds,NULL,&exception_fds,NULL);        if( ret  ==  -1)        {            perror("select");            break;        }        else if( ret == 0)        {            perror("timeout");            break;        }        for(vector<int>::iterator it = connFds.begin();it != connFds.end();)        {            memset(buf,0,sizeof(buf));            if( FD_ISSET(*it,&read_fds) )            {                int ret = recv(*it,buf,sizeof(buf)-1,0);                if(ret <= 0)                {                    perror("recv");                    close(*it);                    FD_CLR(*it,&read_fds);                    it = connFds.erase(it);                    printf("A client disconnectd\n");                    continue;                }                    buf[ret] = '\0';                    printf("%s",buf);            }            else  if(FD_ISSET(*it,&exception_fds))            {                int ret = recv(*it,buf,sizeof(buf)-1,MSG_OOB);                if(ret < 0)                {                    perror("exception");                }                else                {                    buf[ret] = '\0';                    printf("%s",buf);                }            }            ++it;        }        if( FD_ISSET(server_sockfd,&read_fds) )        {            //接受连接,并将被接受的远端sock地址信息保存在第二个参数中            int newfd = accept(server_sockfd,(struct sockaddr*)&client_addr,&client_addrlength);            if(newfd < 0)            {                perror("accept");                return -1;            }            else            {                connFds.push_back(newfd);                max_fd = newfd;                //inet_ntoa(struct addr_in) 将IP地址转换为字符串并返回                //只是从监听队列中取出连接,即使客户端已经断开网络连接也会accept成功                printf("accept client_addr %s\n",inet_ntoa(client_addr.sin_addr));            }        }    }    //关闭连接,实际只是socket的引用-1,必须引用为0才会真正关闭    for(int i= 0;i< connFds.size();++i)    {        close(connFds[i]);    }    close(server_sockfd);    return 0;}
0 0
原创粉丝点击