common way to use socket is to open GIOChannel and then add watch - asynchron function. here is my sample - I use UDP datagram, but you can easy change to TCP stream as well.
Code:
gboolean
init_udp_server ()
{
struct sockaddr_in ip4addr; // socket address
// struct hostent *he; // host
GError *err = NULL;
sock = g_socket_new(G_SOCKET_FAMILY_IPV4,
G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP,
&err);
if (err)
{
g_error_free (err);
g_print (" %s\n", err->message);
return TRUE;
}
// g_assert(err == NULL);
/*
if ((he = gethostbyname("localhost")) == NULL)
{
g_print ("gethostbyname() error !");
return;
}
*/
ip4addr.sin_family = AF_INET;
ip4addr.sin_port = htons(4950); // listen port
inet_pton (AF_INET, "192.168.1.101", &ip4addr.sin_addr); // source address
// ip4addr.sin_addr = *((struct in_addr *)he->h_addr); // listen at host addres
memset(&(ip4addr.sin_zero), '\0', 8);
GSocketAddress *addr = g_socket_address_new_from_native (&ip4addr, sizeof ip4addr);
g_socket_bind(sock,
G_SOCKET_ADDRESS (addr),
TRUE,
&err);
if (err)
{
g_error_free (err);
g_print (" %s\n", err->message);
return TRUE;
}
// g_assert(err == NULL);
g_socket_set_blocking (sock, FALSE);
// we already BIND source, now DEST addr
ip4addr.sin_family = AF_INET;
ip4addr.sin_port = htons(4951); // send to port
inet_pton (AF_INET, "192.168.1.102", &ip4addr.sin_addr); // dest address
memset(&(ip4addr.sin_zero), '\0', 8);
dest_addr = g_socket_address_new_from_native (&ip4addr, sizeof ip4addr);
cancel = g_cancellable_new (); // za potrebe send_to
/*
To get an event when the socket receives data, the following steps are necessary:
Get a file descriptor for the socket.
Use the file descriptor to create a GIOChannel for the socket.
Add a watch for the G_IO_IN condition on the channel.
*/
int fd = g_socket_get_fd(sock);
GIOChannel *channel = g_io_channel_unix_new(fd);
guint source = g_io_add_watch(channel, G_IO_IN,
(GIOFunc) recv_cb_func, NULL);
g_io_channel_unref(channel);
g_object_unref (addr);
return FALSE;
/*
* GIOFunc must not block
* Cleaning up is pretty simple: Use g_source_remove(source) to disconnect the event source
* and g_object_unref() the objects.
*/
}
after that init part, you need GIOFunc , I call it RECV_CB_FUNC . It can look something like this:
Code:
// Callback for UDP listener , GIOFunc
static gboolean
recv_cb_func (GIOChannel *source, GIOCondition *cond, gpointer dta)
{
gchar *buffer = (gchar *) g_malloc0 (128);
GError *error = NULL;
gsize size = 86;
gssize b_read = 0;
b_read = g_socket_receive (sock, buffer, size, NULL, &error);
if (error)
{
g_print (" %s\n", error->message);
g_error_free (error);
g_free (buffer);
return FALSE; // close CHANNEL !
}
g_print("Got: %d: %s\n", b_read, buffer);
if (b_read == 86)
{
// length 86 bytes for data payload of UDP packet
// do something
recv_paket = TRUE;
} // total 86 ok
g_free (buffer);
return TRUE; // source remain open
}
here I set RECV_PAKET flag to TRUE - so I can do more in main loop. You can process received data immidietly, or just set some flags, it is up to you. If you work with TCP stream, you will change a way to handle stream of data.
This is just a piece of code, hope it can help.
Some day I will put complete sample in PROJECTS forum ;)
Cheers !