龙空技术网

socket的select使用

求索9N8U 231

前言:

此刻你们对“socket select 返回0”大概比较注重,朋友们都需要剖析一些“socket select 返回0”的相关文章。那么小编同时在网上收集了一些有关“socket select 返回0””的相关内容,希望大家能喜欢,小伙伴们快快来了解一下吧!

int select(int nfds, readfds, writefds, exceptfds, timeou);

nfds:linux上的socket也叫做fd,将这个参数的值设置为所需要使用select函数检测事件的fd中的最大值加1

readfds: 需要监听可读事件的fd集合

writefds: 需要监听可写事件的fd集合

exceptfds: 需要监听异常事件的fd集合

timeouts:超时时间,即在这个参数设定的时间内检测这些fd的事件,超过事件后,select函数理解返回

select 用于检测在一组socket中是否有事件就绪

读事件就绪

1、 在socket内核中,接收缓冲区中的字节数大于或等于低水位标记SO_RCVLOWAT,此时调用recv或read函数可以无阻塞的读该文件描述符,并且返回值大于0。

2、TCP连接的对端关闭连接,此时本端调用recv或read函数对socket进行读操作, recv或read函数会返回0值。

3、在监听socket上有新的连接请求。

4、在socket上有未处理的错误。

写事件就绪

1、在socket内核中,发送缓冲区中的可用字节数大于或等于低水位标记SO_SNDLOWAT,可用无阻塞的写,并且返回值大于0。

2、socket的写操作被关闭时,对一个写操作被关闭的socket进行写操作,会触发SIGPIPE信号。

3、socket使用非阻塞connect连接成功或失败时。

异常事件就绪

需要在fd_set中删除一个fd,即将对应的bit置0,则可用使用FD_CLR。 void FD_CLR(int fd, fd_set *set)。

需要在fd_set中清除所有fd,即将所有的bit置0,则可用使用FD_ZERO。 void FD_ZERO(fd_set *set)。

FD_ISSET宏判断在某个fd中是否有我们关心的事件。int FD_ISSET(int td, fd_set *set).

#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <unistd.h>#include <iostream>#include <string.h>#include <sys/time.h>#include <vector>#include <error.h> #define INVALID_FD -1// int select(int nfds, readfds, writefds, exceptfds, timeou);// nfds:linux上的socket也叫做fd,将这个参数的值设置为所需要使用select函数检测事件的fd中的最大值加1// readfds: 需要监听可读事件的fd集合// writefds: 需要监听可写事件的fd集合// exceptfds: 需要监听异常事件的fd集合// timeouts:超时时间,即在这个参数设定的时间内检测这些fd的事件,超过事件后,select函数理解返回// select 用于检测在一组socket中是否有事件就绪// 读事件就绪//  1、 在socket内核中,接收缓冲区中的字节数大于或等于低水位标记SO_RCVLOWAT,此时调用recv或read函数可以无阻塞的读该文件描述符,并且返回值大于0。//  2、TCP连接的对端关闭连接,此时本端调用recv或read函数对socket进行读操作, recv或read函数会返回0值。//  3、在监听socket上有新的连接请求。//  4、在socket上有未处理的错误。// 写事件就绪//  1、在socket内核中,发送缓冲区中的可用字节数大于或等于低水位标记SO_SNDLOWAT,可用无阻塞的写,并且返回值大于0。//  2、socket的写操作被关闭时,对一个写操作被关闭的socket进行写操作,会触发SIGPIPE信号。//  3、socket使用非阻塞connect连接成功或失败时。// 异常事件就绪// 需要在fd_set中删除一个fd,即将对应的bit置0,则可用使用FD_CLR。 void FD_CLR(int fd, fd_set *set)。// 需要在fd_set中清除所有fd,即将所有的bit置0,则可用使用FD_ZERO。 void FD_ZERO(fd_set *set)。// FD_ISSET宏判断在某个fd中是否有我们关心的事件。int FD_ISSET(int td, fd_set *set).int main(){    // create socket    int listenfd = socket(AF_INET, SOCK_STREAM, 0);    if (listenfd == INVALID_FD)    {        std::cout << "create listen socket error." << std::endl;        return -1;    }    // init server address    struct sockaddr_in bindaddr;    bindaddr.sin_family = AF_INET;    bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);    bindaddr.sin_port = htons(3000);    if (bind(listenfd, (struct sockaddr*)&bindaddr, sizeof(bindaddr)) == -1)    {        std::cout << "bind listen socket error" << std::endl;        close(listenfd);        return -1;    }    if (listen(listenfd, SOMAXCONN) == -1)    {        std::cout << "listen error" << std::endl;         close(listenfd);        return -1;    }    std::vector<int> clientfds;    int maxfd;    while (true)    {        fd_set readset;        FD_ZERO(&readset);        FD_SET(listenfd, &readset);        maxfd = listenfd;        int clientfdslength = clientfds.size();        for (int i = 0; i < clientfdslength; ++i)        {            if (clientfds[i] != INVALID_FD)            {                FD_SET(clientfds[i], &readset);                if (maxfd < clientfds[i])                 {                    maxfd = clientfds[i];                }            }        }        timeval tm;        tm.tv_sec = 1;        tm.tv_usec = 0;        int ret = select(maxfd + 1, &readset, NULL, NULL, &tm);        if (-1 == ret)        {            if (errno != EINTR)            {                std::cout << "error: " << errno << std::endl;                break;            }        }         else if (0 == ret)        {            continue;        }        else         {            if (FD_ISSET(listenfd, &readset))            {                struct sockaddr_in  clientaddr;                socklen_t clientaddrlen = sizeof(clientaddr);                int clientfd = accept(listenfd, (struct sockaddr*)&clientaddr, &clientaddrlen);                if (clientfd == INVALID_FD)                {                    std::cout << "clientfd == INVALID_FD" << std::endl;                    break;                }                std::cout << "accept a client connection, fd:" << clientfd << std::endl;                clientfds.push_back(clientfd);            }            else             {                char recvbuf[64];                int clientfdslength = clientfds.size();                for (int i = 0; i < clientfdslength; ++i)                {                    if (clientfds[i] != INVALID_FD && FD_ISSET(clientfds[i], &readset))                    {                        memset(recvbuf, 0, sizeof(recvbuf));                        int length = recv(clientfds[i], recvbuf, 64, 0);                        if (length <= 0)                        {                            std::cout << "recv data error, clientfd:" << clientfds[i] << std::endl;                            close(clientfds[i]);                            clientfds[i] == INVALID_FD;                            continue;                        }                        std::cout << "clientfd: " << clientfds[i] << ", recv data: " << recvbuf << std::endl;                    }                }            }        }    }    int clientfdslength = clientfds.size();    for (int i = 0; i < clientfdslength; ++i)    {        if(clientfds[i] != INVALID_FD)        {            close(clientfds[i]);        }    }    std::cout << "end" << std::endl;    close(listenfd);    return 0;}

标签: #socket select 返回0 #socket返回值小于零怎么办 #socket select 返回 1