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?
2 Answers
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

- 50,202
- 14
- 95
- 141
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()

- 2,603
- 2
- 20
- 26