John Doe
John Doe

Reputation: 1

Find out if the socket was accepted or not

I have basic example of using poll() method:

struct pollfds fds[5];
int nfds = 1;

fds[0].fd = listen_sd;
fds[0].events = POLLIN;

while(1) {
    int ret = poll(fds, nfds, 0);

    if (ret < 0) {
        exit(1);
    }

    int size = nfds;

    for (int i = 0; i < size; i++) {
        if (fds[i].revents == 0) {
            continue;
        }

        if (fds[i].revents != POLLIN) {
            exit(1);
        }

        if (fds[i].fd == listen_sd) {
            // Something happened on the server
            // If there is a client which wasn't accepted yet, it returns its fd
            int new = accept(listen_sd, null, null);
            // If there is a client which was already accepted,
            // it doesn't return anything, just loop in accept() method

        } else {
            // Something happened on a different socket than the server
        }
    }
}

All messages from clients will flow through server socket.

It means there is always something happened on the server socket, isn't it?

But how can I do something like this (in true condition):

Upvotes: 0

Views: 334

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596297

On the server side, a TCP socket listening for connections will enter a readable state when it has a client connection waiting to be accepted. Call accept() to actually accept the connection, and then you can start monitoring for read/write/close states on the new TCP socket returned by accept(). This is a completely separate socket than the one that is listening for connections. Add it to your pollfds array so you can poll both it and the listening socket at the same time.

Try something like this:

#include <vector>

std::vector<pollfds> fds;

{
pollfds listen_pf;
listen_pf.fd = listen_sd;
listen_pf.events = POLLIN;
listen_pf.push_back(listen_pf);
}

while (true) {
    int ret = poll(fds.data(), fds.size(), 0);
    if (ret < 0) {
        exit(1);
    }

    size_t i = 0, size = fds.size();

    while (i < size) {
        if (fds[i].revents & POLLIN) {
            if (fds[i].fd == listen_sd) {
                // accept a pending client connection...
                int client_sd = accept(listen_sd, NULL, NULL);
                if (client_sd != -1) {
                    pollfds client_pf;
                    client_pf.fd = client_sd;
                    client_pf.events = POLLIN | POLLOUT | POLLRDHUP;
                    fds.push_back(client_pf);
                }
            }
            else {
                // read data from fds[i].fd as needed...
                if (read fails) {
                    fds.erase(fds.begin()+i);
                    --size;
                    continue;
                }
            }
        }

        if (fds[i].revents & POLLOUT) {
            // write pending data to fds[i].fd as needed ...
            if (write fails) {
                fds.erase(fds.begin()+i);
                --size;
                continue;
            }
        }

        if (fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) {
            if (fds[i].fd == listen_fd) {
                exit(1);
            }
            else {
                fds.erase(fds.begin()+i);
                --size;
                continue;
            }
        }

        ++i;
    }
}

On the client side, a TCP socket connecting to a server will enter a writable state when connect() is successful and the connection has been fully established with the server and is ready for I/O.

Upvotes: 1

Related Questions