Re: [gnet] non-blocking UDP sockets



On Wed, 2006-11-01 at 09:23 +0000, Tim Müller wrote:
> On Tue, 2006-10-31 at 11:10 -0500, Mark Drago wrote:
> 
> Hi Mark,
> 
> > I use GTcpSocket in a non-blocking way by calling
> > gnet_tcp_socket_get_io_channel() to get the GIOChannel and then using
> > g_io_channel_set_flags() to flip the G_IO_FLAG_NONBLOCK bit.  Then,
> > whenever I want to read or write to the socket I use
> > g_io_channel_read/write_chars() directly.  This is working out fine.
> 
> You have seen the GConn API providing an async wrapper for GTcpSocket,
> right?

I have seen the GConn API.  If I remember correctly I decided against
using it because it seems like I can only have one event handler for a
connection at any one time.  That is, I can't say that if the socket is
readable call func1 and if it is writable call func2.  I suppose it
could be handled by calling one function which would act as a traffic
cop and either call func1 or func2 depending on the GConnEvent, but I
thought using GIOChannel directly would be cleaner.

> > I am wondering how I would be able to do the same thing with UDP
> > sockets.  The GUdpSocket documentations says the following:
> > "gnet_udp_socket_send() will block if the OS cannot buffer the packet
> > immediately. gnet_udp_socket_receive() will block until there is a
> > packet available to receive."  But, it also says the following: "Note
> > that a UDP socket's GIOChannel is not a normal GIOChannel -- it should
> > not be written to or read from directly."
> 
> I think the latter remark means that you shouldn't use GIOChannel
> functions for reading or writing data to this special UDP GIOChannel,
> but only gnet_udp_socket_receive() and _send().
> 
> You should still be able to do async I/O on this GIOChannel the usual
> way, namely by setting up an IO watch with g_io_add_watch(). Use the
> G_IO_IN flag to be notified whenever a packet arrives (which you can
> then read without blocking using gnet_udp_socket_receive()) and the
> G_IO_OUT flag to be notified whenever the socket is ready for sending
> data (you will probably need to remove the watch and set up a new
> read-only one again once you've sent all your data, or your callback
> will be called all the time with 'ready to send').

That's basically how I'm doing it now.  I was seeing a problem where
rarely after a G_IO_OUT event was triggered on a GIOChannel, writing to
the socket would cause the program to block indefinitely.  I reasoned
that this was caused by trying to write more data in to the socket than
the OS buffer could hold.  So, if there was 6K of space in the buffer
and I tried to write 8K, write() would block until it was able to write
the remaining 2K and that would never happen for some reason.  After
that I made sure that all of the GIOChannels that belong to GTcpSockets
are marked with G_IO_FLAG_NONBLOCK.  I was hoping to avoid a similar
problem with UDP sockets at some point in the future.

>  Cheers
>   -Tim

Thanks,
Mark Drago.

Attachment: signature.asc
Description: This is a digitally signed message part



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]