开发者

c++ select issue

So I'm trying 开发者_如何转开发to build a async server... Here is a summary of what I have so far:

int sockfd;
int max;
fd_set socks;
set<int> conns;

bind();
listen(sockfd);

while(1){
    FD_ZERO(&socks);
    max = sockfd;
    FD_SET(sockfd, &socks);
    for(set<int>::iterator it=conns.begin(); it!=conns.end(); it++){
        FD_SET(*it, &socks);
        if(max < *it){
            max = *it;
        }
    }

    int res = select(max+1, &socks, NULL, NULL, NULL);

    if(res < 0){
        cerr << "ERROR with select" << endl;
        break;
    }else if(res){
        if(FD_ISSET(sockfd, &socks)){
            //new connection
            int new_sockfd = accept();
            conns.insert(new_sockfd);
        }else{
            for(set<int>::iterator it=conns.begin(); it!=conns.end(); it++){
                if(FD_ISSET(*it, &socks){
                    char buffer[256];
                    read(buffer, 256, *it);
                    cout << buffer << endl;
                    close(*it);
                    conns.erase(*it);
                }
            }
        }
    }
}

What ends up happening is... If I connect a client-1, and then client-2. And then I try and send data using Client-2 and then Client-1... it works...

However, If I connect client-1 and then connect client-2... and then try to send data using client-1. Select() returns a -1...

Help?


Take a look into man pages for select. The important part is :

Under the following conditions, pselect() and select() shall fail and set errno to:
EBADF
One or more of the file descriptor sets specified a file descriptor that is not a valid open file descriptor.
EINTR
The function was interrupted before any of the selected events occurred and before the timeout interval expired.

If SA_RESTART has been set for the interrupting signal, it is implementation-defined whether the function restarts or returns with [EINTR].
EINVAL
An invalid timeout interval was specified.
EINVAL
The nfds argument is less than 0 or greater than FD_SETSIZE.
EINVAL
One of the specified file descriptors refers to a STREAM or multiplexer that is linked (directly or indirectly) downstream from a multiplexer.

errno should tell you what is wrong.

This is just a quess, but when you close the connection, your file descriptor becomes invalid. I guess the error from select should be EBADF


I think your code erasing from the set is suspect. once you call conns.erase(*it), your iterator is invalid (and incrementing it leads to undefined behavior).

Changing your loop to something like the following should resolve the issue:

for(set<int>::iterator it=conns.begin(); it!=conns.end();)
{
    set<int>::iterator cur = it++;
    if(FD_ISSET(*cur, &socks)){
        char buffer[256];
        read(buffer, 256, *cur);
        cout << buffer << endl;
        close(*cur);
        conns.erase(*cur);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜