Sockets & IO Channels



Hello,

I am trying to create a GTK+ application that would connect to a TELNET
server and all data received from it would be outputted to a GtkTextView
widget in a GtkWindow. The window also has a GtkEntry widget that allows
the user to enter text, which in turn is sent to the server.

I am using GLib IO Channels for the socket input/output. Here is a
sample code from my application:

-----------------------
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <gtk/gtk.h>
#include <glade/glade.h>

/* user interface */
GtkWindow   *terminal = NULL;
GtkTextView *buffer = NULL;
GtkEntry    *input = NULL;

/* event handlers */
void
on_input_activate (GtkEntry *entry, gpointer user_data)
{
  const gchar *text;
  g_assert (entry != NULL);
  text = gtk_entry_get_text (entry);
  g_debug ("Input: %s", text);
  /* TODO: sent the text to the server */
  gtk_entry_set_text (entry, "");
}

static GIOChannel *
open_socket_channel (const char *hostname, int port)
{
  struct hostent *h;
  struct sockaddr_in a;
  int fd;

  g_assert (hostname != NULL);
  g_assert (port > 0);
  
  h = gethostbyname2 (hostname, AF_INET);
  g_assert (h != NULL);

  a.sin_family = AF_INET;
  a.sin_port = htons (port);
  a.sin_addr.s_addr = *((uint32_t *) h->h_addr);

  g_debug ("%s - %d.%d.%d.%d", hostname,
           (a.sin_addr.s_addr & 0x000000ff),
           (a.sin_addr.s_addr & 0x0000ff00) >> 8,
           (a.sin_addr.s_addr & 0x00ff0000) >> 16,
           (a.sin_addr.s_addr & 0xff000000) >> 24);

  fd = socket (PF_INET, SOCK_STREAM, 0);
  g_assert (fd != -1);

  if (connect (fd, (struct sockaddr *) &a, sizeof (a)) == -1)
    {
      /* TODO: error handling */
    }

  return g_io_channel_unix_new (fd);
}

static gboolean
readfunc (GIOChannel *channel, GIOCondition condition, gpointer data)
{
  gchar *str;
  gsize length;

  g_assert (channel != NULL);
  g_assert (buffer != NULL);

  g_io_channel_read_to_end (channel, &str, &length, NULL);
  /* TODO: output the string to the window */
  g_free (str);
  
  return TRUE;
}

int
main (int argc, char **argv)
{
  GladeXML *xml;
  GIOChannel *channel;

  gtk_init (&argc, &argv);

  /* Load the user interface. */
  
  xml = glade_xml_new ("foo.glade", NULL, NULL);
  if (!xml)
    return 0;

  glade_xml_signal_autoconnect (xml);

  terminal = GTK_WINDOW (glade_xml_get_widget (xml, "terminal"));
  buffer = GTK_TEXT_VIEW (glade_xml_get_widget (xml, "buffer"));
  input = GTK_ENTRY (glade_xml_get_widget (xml, "input"));

  g_assert (terminal != NULL);
  g_assert (buffer != NULL);
  g_assert (input != NULL);

  /* Open connection to the server. */

  channel = open_socket_channel ("foo.org", 23);
  g_assert (channel != NULL);

  g_io_channel_set_encoding (channel, NULL, NULL);
  g_io_channel_set_close_on_unref (channel, TRUE);
  g_io_add_watch (channel, G_IO_IN, readfunc, NULL);

  /* Show the main window and run main loop. */

  gtk_widget_show_all (GTK_WIDGET (terminal));
  gtk_main ();

  return 0;
}

------------------------

This however, seems not to be working for some reason. The application
window shows up, but it hangs (not responding to any events). Do I need
to set my socket into non-blocking mode? Is the IO Channels the best way
to handle the socket I/O or is there a better way to do this? Are there
any problems with this method? Any comments or ideas?

- Henri H.





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