"Emulating" polls with fd_set

Started by
9 comments, last by hplus0603 14 years, 2 months ago
Hi guys, i have a netcode that uses polls for polling sockets. But i have to compile it on a system that doesn't support polls, so i made this: #define POLLIN 1 #define POLLOUT 2 #define POLLERR 4 #define POLLHUP POLLERR #define POLLPRI 8 #define POLLNVAL POLLERR struct pollfd { int fd; unsigned char events; //What events to capture unsigned char revents; //Events captured }; int poll(struct pollfd* socklist,int count, int unk) { fd_set read_flags,write_flags; int i=0,ret; struct timeval waitd; int maxfd=0; waitd.tv_sec = 0; waitd.tv_usec = 5; FD_ZERO(&read_flags); FD_ZERO(&write_flags); for (i=0;i<count;i++) { if((socklist->fd)<0) continue; if(socklist->events & POLLIN) FD_SET(socklist->fd, &read_flags); if(socklist->events & POLLOUT) FD_SET(socklist->fd, &write_flags); if ((socklist->fd)>maxfd) { maxfd=socklist->fd; } } ret=select((maxfd)+1, &read_flags,&write_flags,(fd_set*)0,&waitv); if(ret<0) { //Error handling } for (i=0;i<count;i++) { if((socklist->fd)<0) continue; if(socklist->events & POLLIN) if(FD_ISSET(socklist->fd,&read_flags)) { socklist->revents |=POLLIN; } if(socklist->events & POLLOUT) if(FD_ISSET(socklist->fd,&write_flags)) { socklist->revents |=POLLOUT; } } return 1; } Is it right? Cause FD_ISSET always return 1, so the program thinks that the socket is ready for send and recv when it's not.... Why?
Advertisement
I think there is an error condition whereby a socket can be flagged as ready to receive, you then need to check to see how much data is waiting, if data == 0, then the socket was closed.

Here is some of my socket code:
if (m_clientSocket->Select(                    (int)(socketFD)+1,                    &readSet,                    &writeSet,                    NULL,                    0) != -1){    if (FD_ISSET(socketFD, &readSet))    {        res |= PRES_CAN_RECIEVE;    }    if (FD_ISSET(socketFD, &writeSet))    {        res |= PRES_CAN_SEND;    }    //-----------------------------    // Check to see if the socket has been closed    //-----------------------------    if (res & PRES_CAN_RECIEVE)    {        char buffer[1];        if (recv(m_clientSocket->GetSocketDescriptor(),                            buffer,                            1,                            MSG_PEEK) == 0)        {            res = PRES_CONNECTION_CLOSED;        }    }}else{    HandleSocketError();    return PRES_ERROR_OCCURED;}


Regards,

Alex

Twitter: [twitter]CaffinePwrdAl[/twitter]

Website: (Closed for maintainance and god knows what else)

I don't think that the recv is the problem.
The problem (i think) is that connect is non-blocking, so after the connect it's flagged as writable also if it's not still connected
Does ISSET_FD return true for both read and write, or just one of them?

If you are testing a socket, it will most likely come back as ready to send (unless the output buffer is full), but not receive unless data is actually waiting (or if socket was closed as in my last post).

Alex

Twitter: [twitter]CaffinePwrdAl[/twitter]

Website: (Closed for maintainance and god knows what else)

it always tell me that i can both read and write, and the socket is connecting/connected, so it is not closed
I don't see you clearing revents in your emulation code.
In your first "count" loop, you should probably clear that to 0.
enum Bool { True, False, FileNotFound };
I found the problem:
the connect is async so it returns immediately, and it takes some time to connect.
But select returns that the socket is ready to send.
And when i send, errno is 128 (ENOTCONN 128 /* Socket is not connected */)
Probably because it's still connecting.
So, why does select tells me that the socket is ready to send?
As I understand it, select doesn't attempt to guess at the state of your connection. It simply tells you whether that socket is physically ready for reading or writing (usually based on buffer contents or free space). How much data you get or where it goes when you send it is another matter.
Quote:Original post by Kylotan
As I understand it, select doesn't attempt to guess at the state of your connection. It simply tells you whether that socket is physically ready for reading or writing (usually based on buffer contents or free space). How much data you get or where it goes when you send it is another matter.


The socket is NOT physically ready for writing because it's not still connected, but select tells me that the socket is ready for sending and receiving
The socket IS physically ready because it's got free buffer space for you to fill up. Select's readiness does not tell you "whatever you send will arrive at the intended destination". Select tells you "if you write something now, I won't have to tell you to wait while I make room to buffer the data".

This topic is closed to new replies.

Advertisement