On Wednesday 23 February 2011 08:01:12 you wrote: > On Tue, 22 Feb 2011 23:25:43 -0500 > Jacques Pelletier <jpellet...@ieee.org> wrote: > [snip] > > > ... > > > > /* Connect asynchronously */ > > > > mySocketClient = g_socket_client_new(); > > > > g_socket_client_connect_to_host_async( > > > > mySocketClient, > > myUrl, > > myPort, > > NULL, > > my_client_connect_async_function, > > NULL); > > > > ... > > > > > > void my_client_connect_async_function(GObject *source_object, > > > > GAsyncResult *res, > > gpointer user_data) > > > > { > > > > mySocketConnection = > > > > g_socket_client_connect_to_host_finish(source_object,res,NULL); > > > > if (mySocketConnection != NULL) > > > > { > > > > mySocket = g_socket_connection_get_socket(mySocketConnection); > > mySource = g_socket_create_source(mySocket, > > > > G_IO_IN > > | > > | G_IO_PRI | G_IO_NVAL, NULL); > > | > > g_source_set_callback(mySource, myCallback,NULL,NULL); > > mySource_id = g_source_attach(mySource,NULL); > > > > /* Instructions for updating the GUI */ > > > > } > > > > else > > { > > > > /* Socket connection failed */ > > > > } > > > > } > > > > /* Process incoming data from socket */ > > gboolean myCallback(GSocket *source, GIOCondition condition, gpointer > > data) { > > > > int Input_Length; > > gchar Receive_Buffer[1024]; > > > > switch (condition) > > > > { > > > > /* Check for socket error */ > > > > case (G_IO_ERR | G_IO_HUP): > > > > case G_IO_HUP: > > g_message("Socket error HUP\n"); > > > > PortClose(); > > > > goto error; > > > > case (G_IO_ERR | G_IO_NVAL): > > > > case (G_IO_NVAL): > > g_message("Socket error NVAL\n"); > > goto error; > > > > /* Check for data to be read (or if the socket was closed) > > > > */ case G_IO_IN: > > Input_Length = g_socket_receive(source, (gchar > > > > *)Receive_Buffer,1024,NULL,NULL); > > > > if (Input_Length != -1) > > > > { > > > > /* Update GUI according to the received data > > > > */ MyGuiUpdate(Receive_Buffer,Input_Length); > > > > } > > > > break; > > > > default: > > ; > > > > } /* condition */ > > > > /* Returns TRUE so it remains installed until we remove it */ > > return TRUE; > > > > error: > > return FALSE; > > > > } > > > > void SocketClose(void) > > { > > > > g_socket_close(mySocket,NULL); > > g_object_unref(mySocketConnection); > > g_object_unref(mySocketClient); > > g_source_unref(mySource); > > > > } > > > > > > Any comments about how to improve, missing code, etc.? > > Your callback seems to rely on the ability reliably to detect an > end-of-file on the socket by means of the G_IO_HUP revent poll > condition. However, you can't rely on that: see > http://www.greenend.org.uk/rjk/2001/06/poll.html . > > From looking at the implemention of g_socket_receive_with_blocking() in > gio's socket.c, g_socket_receive() returns 0 (like recv()/read()) > rather than returning -1 and an error, on encountering end-of-file (to > that extent the statement in the documentation that "if the socket is > in blocking mode the call will block until there is some data to > receive or there is an error" appears to be wrong, since it will also > unblock on orderly close down of the remote peer). However, your code > doesn't act on either outcome from g_socket_receive(). > > I also didn't understand your switch fall-throughs - I avoid bit > testing in switch statements - but they appear to treat G_IO_ERR and > G_IO_HUP as the same, and view G_IO_HUP as an error, which it isn't > except in the limited sense that you don't expect the server to close > its end first. A G_IO_HUP event will become G_IO_ERR on further read > attempts of course, and maybe that was your design approach on that > point, except that your switch statements don't accommodate a case where > the G_IO_ERR flag is set and none of the others are. > > On a minor point, in this kind of usage I always call g_source_unref() > immediately after g_source_attach() (g_source_attach() will increment > the reference count).
I wasn't sure when exactly was the best moment to call g_source_unref(). I'm not very familiar with this concept and I don't know if there could be some problems with memory allocations and releases. > This saves having to call it in SocketClose() > (instead the source object will be destroyed as soon as the callback > returns FALSE). As it happens, SocketCLose() isn't called in your code > snippet but no doubt something else does that. > > As someone else has mentioned however, GSocketConnection inherits from > GIOStream, and if you use the GIOStream interface you can do an > asynchronous read with g_input_stream_read_async() via > g_io_stream_get_input_stream(), which does all this stuff for you. If it makes the code simpler and easier to read, I'll go with that. Many thanks for your contribution, I'll check all that carefully. JP > > Chris _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list