Reputation: 1
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):
Try to accept a socket, some function should return: the socket is already accepted, the socket hasn't been accepted yet.
When the socket is already accepted - receive the data.
When the socket hasn't been accepted yet - accept the socket and receive the data.
Upvotes: 0
Views: 334
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