пример GIO socket-server/-client

Я хотел бы создать серверное и клиентское приложение, которые взаимодействуют через сокеты с использованием GIO. GSocketService и GSocketClient кажутся идеальными для этой цели, но, к сожалению, я не смог найти какой-либо учебник или пример кода (который может понять новичок GLib, GIO,...). Кто-нибудь знает хорошие ресурсы или может разместить пример кода здесь?


person drakide    schedule 01.03.2012    source источник
comment
Вы добились какого-либо прогресса? Я ищу то же самое. Помимо API и этого ТАК ответьте Я ничего не нашел.   -  person noisebleed    schedule 09.04.2012
comment
@noisebleed: Да, я действительно добился прогресса. На самом деле я не понимаю, почему я не смог создать и сервер, и клиент с первой попытки. Наверное, мне не стоит одновременно изучать C, glib и OGRE.   -  person drakide    schedule 10.04.2012


Ответы (2)


Наконец-то мне удалось создать простой сервер и клиент с помощью glib и gio.
Мой сервер выглядит так:

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

/* this function will get called everytime a client attempts to connect */
gboolean
incoming_callback  (GSocketService *service,
                    GSocketConnection *connection,
                    GObject *source_object,
                    gpointer user_data)
{
  g_print("Received Connection from client!\n");
  GInputStream * istream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
  gchar message[1024];
  g_input_stream_read  (istream,
                        message,
                        1024,
                        NULL,
                        NULL);
  g_print("Message was: \"%s\"\n", message);
  return FALSE;
}

int
main (int argc, char **argv)
{
  /* initialize glib */
  g_type_init();

  GError * error = NULL;

  /* create the new socketservice */
  GSocketService * service = g_socket_service_new ();

  /* connect to the port */
  g_socket_listener_add_inet_port ((GSocketListener*)service,
                                    1500, /* your port goes here */
                                    NULL,
                                    &error);

  /* don't forget to check for errors */
  if (error != NULL)
  {
      g_error (error->message);
  }

  /* listen to the 'incoming' signal */
  g_signal_connect (service,
                    "incoming",
                    G_CALLBACK (incoming_callback),
                    NULL);

  /* start the socket service */
  g_socket_service_start (service);

  /* enter mainloop */
  g_print ("Waiting for client!\n");
  GMainLoop *loop = g_main_loop_new(NULL, FALSE);
  g_main_loop_run(loop);
  return 0;
}

и это соответствующий клиент:

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

int
main (int argc, char *argv[])
{
   /* initialize glib */
  g_type_init ();

  GError * error = NULL;

  /* create a new connection */
  GSocketConnection * connection = NULL;
  GSocketClient * client = g_socket_client_new();

  /* connect to the host */
  connection = g_socket_client_connect_to_host (client,
                                               (gchar*)"localhost",
                                                1500, /* your port goes here */
                                                NULL,
                                                &error);

  /* don't forget to check for errors */
  if (error != NULL)
  {
      g_error (error->message);
  }
  else
  {
      g_print ("Connection successful!\n");
  }

  /* use the connection */
  GInputStream * istream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
  GOutputStream * ostream = g_io_stream_get_output_stream (G_IO_STREAM (connection));
  g_output_stream_write  (ostream,
                          "Hello server!", /* your message goes here */
                          13, /* length of your message */
                          NULL,
                          &error);
  /* don't forget to check for errors */
  if (error != NULL)
  {
      g_error (error->message);
  }
  return 0;
}

Обратите внимание, что я все еще новичок в glib, gio и даже C, поэтому дважды проверьте мой код, прежде чем использовать его.

person drakide    schedule 10.04.2012
comment
Спасибо, что поделились этим. Это будет бесценный ресурс для новичков GIO. Справочная документация хороша, но примеров не хватает. - person noisebleed; 10.04.2012
comment
@noisebleed: такое же мнение о документации здесь. - person drakide; 11.04.2012
comment
на самом деле, вы можете использовать одну такую ​​команду echo anyword |nc localhost 1500 в качестве клиента, чтобы проверить, работает ли сервер. - person mxi1; 08.04.2014
comment
Было бы здорово, если бы вы могли прочитать ответ с сервера. - person diega; 29.05.2016
comment
неопределенная ссылка на `g_io_stream_get_type'| ПОМОЩЬ! - person Samuel; 22.11.2016
comment
Добавить pkg-config --cflags --libs glib-2.0 gio-2.0 - person Samuel; 22.11.2016

Обратный вызов от входящего не должен блокироваться, из документации gio: «Обработчик должен инициировать обработку соединения, но не может блокировать; по сути, должны использоваться асинхронные операции».

У меня были некоторые проблемы с соединением в асинхронной версии, оно должно быть передано пользователем, иначе соединение будет закрыто после возврата входящего обратного вызова.

Полный пример сервера, который не блокируется, на основе примера, приведенного ранее:

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

#define BLOCK_SIZE 1024
#define PORT 2345

struct ConnData {
  GSocketConnection *connection;
  char message[BLOCK_SIZE];
};

void message_ready (GObject * source_object,
    GAsyncResult *res,
    gpointer user_data)
{
  GInputStream *istream = G_INPUT_STREAM (source_object);
  GError *error = NULL;
  struct ConnData *data = user_data;
  int count;

  count = g_input_stream_read_finish (istream,
      res,
      &error);

  if (count == -1) {
    g_error ("Error when receiving message");
    if (error != NULL) {
      g_error ("%s", error->message);
      g_clear_error (&error);
    }
  }
  g_message ("Message was: \"%s\"\n", data->message);
  g_object_unref (G_SOCKET_CONNECTION (data->connection));
  g_free (data);
}

static gboolean
incoming_callback (GSocketService *service,
    GSocketConnection * connection,
    GObject * source_object,
    gpointer user_data)
{
  g_message ("Received Connection from client!\n");
  GInputStream *istream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
  struct ConnData *data = g_new (struct ConnData, 1);

  data->connection = g_object_ref (connection);

  g_input_stream_read_async (istream,
      data->message,
      sizeof (data->message),
      G_PRIORITY_DEFAULT,
      NULL,
      message_ready,
      data);
  return FALSE;
}

int main ()
{
  GSocketService *service;
  GError *error = NULL;
  gboolean ret;

  service = g_socket_service_new ();
  ret = g_socket_listener_add_inet_port (G_SOCKET_LISTENER (service),
      PORT, NULL, &error);

  if (ret && error != NULL)
  {
    g_error ("%s", error->message);
    g_clear_error (&error);
    return 1;
  }

  g_signal_connect (service,
      "incoming",
      G_CALLBACK (incoming_callback),
      NULL);

  g_socket_service_start (service);
  GMainLoop *loop = g_main_loop_new(NULL, FALSE);
  g_main_loop_run(loop);

  /* Stop service when out of the main loop*/
  g_socket_service_stop (service);
  return 0;
}
person Fujii    schedule 13.08.2014