Re: Using GSocket in a GTK application
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). 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. Chris ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Using GSocket in a GTK application
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
Re: Using GSocket in a GTK application
On Sunday 13 February 2011 22:17:12 Jacques Pelletier wrote: Hi all, I'm using GSocket in a GTK application in non-blocking mode. Once the connection is done, I'm creating a source for the main event loop: my_source = g_socket_create_source(my_socket, my_events, NULL); How do we specify a callback? Should I use g_source_set_callback ()? The callback would handle the input side from the host to my application. I've been able to work this out. Here is how I implemented the client side: ... /* 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.? I'm now working on the server side and post the result here for convenience. Thanks, JP ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Using GSocket in a GTK application
Any comments about how to improve, missing code, etc.? I would personally recommend taking a look at the GIOStream API for processing data sent through the connection, it would help save a bit of the low-level worries and allow you to get automatically-buffered input through the help of GBufferedInputStream/GDataInputStream. -- Nader Morshed morshed.na...@gmail.com ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Using GSocket in a GTK application
Hi all, I'm using GSocket in a GTK application in non-blocking mode. Once the connection is done, I'm creating a source for the main event loop: my_source = g_socket_create_source(my_socket, my_events, NULL); How do we specify a callback? Should I use g_source_set_callback ()? The callback would handle the input side from the host to my application. Thanks, JP ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list