6

I'm working on a chat application using C and unix low level sockets. I have succeeded in making the console version, but I want to make a GUI for the application. I would like to use GTK for the GUI. my problem is how to "synchronize" the socket and the GUI. because I have to call gtk_main() as the last GTK statement and the application itself is an infinite loop. How can I update the GUI when a message comes in?

Carlo Wood
  • 5,648
  • 2
  • 35
  • 47
Random
  • 467
  • 1
  • 4
  • 9

2 Answers2

9

You are facing the problem that you have several event systems at once but only one thread. Gtk+ comes with its own event handler, that eventually boils down to a select() which will wake up on any user input or other gtk event. You yourself want to handle networking with your own event handling, which typically consists of a select() on your socket(s) or using the sockets in blocking mode.

One solution is to integrate your events into the event loop of Gtk+.

You can make Gtk+ watch/select() your sockets and call a specific function when their state changes (data readable). See the section "Creating new source types" on http://developer.gnome.org/glib/2.30/glib-The-Main-Event-Loop.html

Another solution would be to use Gtk+ networking functionality.

Typically you don't want to do something so special with the sockets that it is not easily wrapable with Glib IO Channels. See http://developer.gnome.org/glib/2.30/glib-IO-Channels.html

A third solution is to start a second thread that handles your networking, e.g. with posix threads or Gtk+ threading functionality.

Separating GUI from the worker part of your application is in general a good idea. However for a chat application, it probably does not give any benefit over the other solutions. See http://developer.gnome.org/glib/2.30/glib-Threads.html

ypnos
  • 50,202
  • 14
  • 95
  • 141
1

This is an example in python with pygobject using GLib.IOChannel to add a watch in the gtk main event loop.

One watch is for listening to new connections. The other for receiving data.

This is adapted from this pygtk example: http://rox.sourceforge.net/desktop/node/413.html

import gi    
gi.require_version('Gtk', '3.0')    
from gi.repository import Gtk, GLib;    
from socket import socket    
    
def listener(io, cond, sock):    
    conn = sock.accept()[0]    
    GLib.io_add_watch(GLib.IOChannel(conn.fileno()),0,GLib.IOCondition.IN, handler, conn)    
    return True    
    
def handler(io, cond, sock):    
    print(sock.recv(1000))    
    return True    
    
s = socket()    
s.bind(('localhost', 50555))    
s.listen()    
GLib.io_add_watch(GLib.IOChannel(s.fileno()), 0, GLib.IOCondition.IN, listener, s)    
    
Gtk.main()    
nadapez
  • 2,603
  • 2
  • 20
  • 26