1

I am trying to learn gio library, especially the giostream and gthreadedsocketservice. I want to write a simple server that:

  1. Each incoming connection will be handled by an individual new thread
  2. At the client side, user types a string and it will be sent to the server; at the server side upon receiving the string, immediately displays it to stdout.
  3. Unless server or client is terminated, the connection is not closed. Namely multiple messages can be sent from client to server without the need to connect multiple times.

The code I tried is: Client-side:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gio/gio.h>

int main(int argc, char* argv[]){
 GError* error = NULL;
 GSocketConnection* connection = NULL;
 GOutputStream* ostream = NULL;
 GSocketClient* client = g_socket_client_new();
 gchar message[1024];

 connection = g_socket_client_connect_to_host(client, (gchar*)"localhost", 1500, NULL, &error);

 if (error) {
  g_error(error->message);
  g_error_free(error);
  return 1;
 }
 else g_print("Message: connected.\n");

 while(TRUE){
  scanf("%s", message);
  ostream = g_io_stream_get_output_stream(G_IO_STREAM(connection));
  g_output_stream_write(ostream, message, strlen(message), NULL, &error);
  if (error) {
   g_error(error->message);
   g_error_free(error);
   return 1;
  }
 }

 g_print("Message: client terminated.\n");
 return 0;
}

Server-side:

#include <glib.h>
#include <gio/gio.h>

gboolean run_callback(GThreadedSocketService*, GSocketConnection*, GObject*, gpointer);

int main(int argc, char **argv){
 int port = 1500;
 GError* error = NULL;
 GMainLoop* loop = NULL;
 GThreadedSocketService* service = NULL;

 service = (GThreadedSocketService*)g_threaded_socket_service_new(-1);
 g_socket_listener_add_inet_port((GSocketListener*)service, port, NULL, &error);
 if (error != NULL) {g_error(error->message);}
 g_signal_connect(service, "run", G_CALLBACK(run_callback), NULL);
 g_socket_service_start((GSocketService*)service);
 g_print("Message: server launched...\n");
 loop = g_main_loop_new(NULL, FALSE);
 g_main_loop_run(loop);

 return 0;
}

gboolean run_callback(GThreadedSocketService* service, GSocketConnection* connection, GObject* source_object, gpointer user_data){
 GInputStream* instream = NULL;
 gchar message[1024];
 GError* error = NULL;

 instream = g_io_stream_get_input_stream(G_IO_STREAM(connection));
 g_input_stream_read_all(instream, message, 1024, NULL, NULL, &error);
 if (error != NULL) {
  g_error(error->message);
  g_error_free(error);
  return FALSE;
 }
 g_print("Received: %s\n", message);

 g_print("Message: connection terminated.\n");
 if (error) g_error_free(error);
 return FALSE;
}

The problem is when I tested it out, on client side I typed three lines:

aaa
bbb
ccc

But nothing is shown on the server side. Only when I exit the client, on the server screen it shows:

aaabbbccc

But what I wanted was when I type "aaa" and entered, it immediately shows up on the server screen.

Any idea on where it goes wrong?

robinchm
  • 109
  • 1
  • 1
  • 7

1 Answers1

1

The problem is that you use g_input_stream_read_all. Notice the suffix all in the name? It means that it will attempt to read the size you pass to it, only returning when it has received all those bytes or there is an error or disconnection.

Instead use e.g. g_input_stream_read in a loop.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Tested and it works. May I ask that when I run a loop within which I call g_input_stream_read(), and there is at the moment no input, does the function return and the loop continues till there is some input (something like polling), or does it block in this thread waiting for the input? – robinchm Aug 26 '15 at 11:31
  • @robinchm Sockets are by default *blocking*, and this goes up all the way in the chain, meaning that when you read from a blocking socket, the read call (whatever function it is) should block until there's something to read. – Some programmer dude Aug 26 '15 at 11:33
  • Thanks a lot! Because gio provides also asynchronous io and different kinds of socketservice in their manuals, but no example to illustrate their usage, I struggled quite a lot learning it. – robinchm Aug 26 '15 at 11:39