Jump to content

  • Log In with Google      Sign In   
  • Create Account

Question about FD_WRITE


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
5 replies to this topic

#1 Vortez   Crossbones+   -  Reputation: 2698

Like
0Likes
Like

Posted 20 September 2013 - 05:26 PM

Hi, im aving trouble finding a bug in my program, then it suddently hit me, im not handling the FD_WRITE event in my code. What happen if you send data and the buffer is full? Could that be the cause of my problem? 

 

If so, how should i handle this? What i though is to set a bool variable to true whenever i receive an FD_WRITE event, then set it to false when i receive WSAEWOULDBLOCK, and only send when the variable is true. Is that right?

 

thx


Edited by Vortez, 20 September 2013 - 05:31 PM.


Sponsor:

#2 SiCrane   Moderators   -  Reputation: 9594

Like
0Likes
Like

Posted 20 September 2013 - 05:33 PM

Assuming you're asking about the socket API, on most system send() blocks until data can be written if in blocking mode, but if in non-blocking mode it returns an error. An exception is if the message is too large for the underlying protocol in which it would return a different error.



#3 Vortez   Crossbones+   -  Reputation: 2698

Like
0Likes
Like

Posted 20 September 2013 - 05:37 PM

Yea, im using winsock sockets in c++, with WSAAsyncSelect, so im using the windows message system to do my stuff, my socket are not blocking.


Edited by Vortez, 20 September 2013 - 05:40 PM.


#4 hplus0603   Moderators   -  Reputation: 5297

Like
0Likes
Like

Posted 20 September 2013 - 05:52 PM

It is totally possible for send() to return less than the full amount of data requested to send.

This is why you typically will want to have a queue of outgoing data, and send from this queue, and only dequeue the data that actually was sent, keeping the rest for the next time around.

 

Also, public service announcement: WSAAsyncSelect() is a very old API, performs very poorly, has known implementation bugs (that Microsoft retains for compatibility reasons,) and is not portable at all. I recommend nobody use it.


enum Bool { True, False, FileNotFound };

#5 Vortez   Crossbones+   -  Reputation: 2698

Like
0Likes
Like

Posted 20 September 2013 - 06:23 PM


It is totally possible for send() to return less than the full amount of data requested to send.

 

Yea, that part i am aware of it. It's handled properly.

 

 

 


This is why you typically will want to have a queue of outgoing data, and send from this queue, and only dequeue the data that actually was sent, keeping the rest for the next time around.

 

That's actually not a bad idea. I was sending my data by chunks in a loop, so that's might be my problem here. Although im not sure it would help much, gotta think about it.

I need to send my data as fast as possible.

 

 


Also, public service announcement: WSAAsyncSelect() is a very old API, performs very poorly, has known implementation bugs (that Microsoft retains for compatibility reasons,) and is not portable at all. I recommend nobody use it.

 

That part i don't understand. I tried polling the socket with select() in my previous version of my projects, and it's seem that each time i called it, it costed me about 1-15 ms,

so that's why i used WSAAsyncSelect(), and it seem to be a lot faster this way... until it crash for no reason, probably because of the FD_WRITE message i forgot to handle.

 

It also make servers that handle multiples connections much easier to deal with, and require no threads to work, althrough now i think im gonna need one to write.

 

And i can't use blocking sockets, because it could hang my program indefinitely.

 

So, i don't have much other options.

 

Also, portability is not an issue here, im only targeting windows machines.

 

EDIT: That's the old code i was using to poll the socket, specifically, my CanRead() function:  (CanWrite() was pretty much identical)

//-----------------------------------------------------------------------------
// Name : CanRead()
// Desc : Tell if we are ready to read data
//-----------------------------------------------------------------------------
bool CNetBaseEngine::CanRead()
{
	// Setup the timeout for the select() call
	timeval waitd;
	waitd.tv_sec  = 0; // Make select wait up to 1 second for data
	waitd.tv_usec = 1; // and 0 milliseconds.

	// Zero the flags ready for using
	fd_set read_flags;
	FD_ZERO(&read_flags);
	
	// Set the read flag to check the write status of the socket
	FD_SET(m_Socket, &read_flags);

	// Now call select
	int Res = select(m_Socket, &read_flags,(fd_set*)0,(fd_set*)0,&waitd);
	if(Res < 0) {  // If select breaks then pause for 5 seconds
		//Sleep(3);  // then continue
		// Socket not ready to read
		return false;
	}

	// If we are ready to read...
	if(FD_ISSET(m_Socket, &read_flags)){
		// Clear the read flag
		FD_CLR(m_Socket, &read_flags);
		// Socket is ready to read
		return true;
	} else {
		// Socket not ready to read
		return false;
	}
}

The problem is, if i used waitd.tv_usec = 0; i would get errors in my program...


Edited by Vortez, 20 September 2013 - 06:39 PM.


#6 hplus0603   Moderators   -  Reputation: 5297

Like
0Likes
Like

Posted 20 September 2013 - 11:35 PM

If you want high performance sockets on Windows, you want to use I/O completion ports with OVERLAPPED I/O.

If you want a nice, portable wrapper on top of this (that uses equally efficient implementations on Linux) then look at boost::asio.

 

Btw: I would be highly surprised if calling select() with a zero timeout would take 1 ms.


enum Bool { True, False, FileNotFound };




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS