Re: Using GSocket in a GTK application

2011-02-23 Thread Chris Vine
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

2011-02-23 Thread Jacques Pelletier
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

2011-02-22 Thread Jacques Pelletier
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

2011-02-22 Thread Nader Morshed
 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

2011-02-13 Thread Jacques Pelletier
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