Sign in to follow this  
roby65

"Emulating" polls with fd_set

Recommended Posts

roby65    154
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[i]->fd)<0) continue; if(socklist[i]->events & POLLIN) FD_SET(socklist[i]->fd, &read_flags); if(socklist[i]->events & POLLOUT) FD_SET(socklist[i]->fd, &write_flags); if ((socklist[i]->fd)>maxfd) { maxfd=socklist[i]->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[i]->fd)<0) continue; if(socklist[i]->events & POLLIN) if(FD_ISSET(socklist[i]->fd,&read_flags)) { socklist[i]->revents |=POLLIN; } if(socklist[i]->events & POLLOUT) if(FD_ISSET(socklist[i]->fd,&write_flags)) { socklist[i]->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?

Share this post


Link to post
Share on other sites
aleks_1661    188
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

Share this post


Link to post
Share on other sites
roby65    154
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

Share this post


Link to post
Share on other sites
aleks_1661    188
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

Share this post


Link to post
Share on other sites
roby65    154
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?

Share this post


Link to post
Share on other sites
Kylotan    10006
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.

Share this post


Link to post
Share on other sites
roby65    154
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

Share this post


Link to post
Share on other sites
Kylotan    10006
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".

Share this post


Link to post
Share on other sites
hplus0603    11356
I seem to have previously learned that an asynchronously connecting socket will not return readable/writable until it's actually connected.
Perhaps the problem is that the socket is still in non-blocking mode, and thus select() detects that a call to send() or recv() will not block. (Pedantically, select says "will not block," not "actually has data")
You could verify this theory by setting the socket back to blocking after calling connect() on it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this