ソフトウェア設計及び演習2017

GDK2017::IOチャネル

「通信」の理解

まずは,プロセス(プログラム)とプロセスがどのようにデータをやり取りするのか,を理解しましょう.

IOチャネル

  • ファイルやパイプ、ソケットを利用するための汎用的な方法
  • メイン・イベント・ループへ統合できる
    • 「通信が来たら、関数を呼び出す」みたいなプログラムが書ける

チャネルの作成

GIOChannel* g_io_channel_new_file (gchar *filename,
                                   gchar *mode,
                                   GError **error);
GIOChannel* g_io_channel_unix_new (int fd);
void g_io_channel_set_close_on_unref (GIOChannel *channel,
                                      gboolean do_close);
GIOStatus g_io_channel_set_encoding (GIOChannel *channel,
                                     const gchar *encoding,
                                     GError **error);
GIOStatus g_io_channel_set_flags (GIOChannel *channel,
                                  GIOFlags flags,
                                  GError **error);

チャネルをメイン・イベント・ループへ追加

guint g_io_add_watch (GIOChannel *channel,
                       GIOCondition condition,
                       GIOFunc func,
                       gpointer user_data);

チャネルの使用

GIOStatus g_io_channel_read_chars (GIOChannel *channel,
                                   gchar *buf,
                                   gsize count,
                                   gsize *bytes_read,
                                   GError **error);
GIOStatus g_io_channel_read_line (GIOChannel *channel,
                                  gchar **str_return,
                                  gsize *length,
                                  gsize *terminator_pos,
                                  GError **error);
GIOStatus g_io_channel_read_to_end (GIOChannel *channel,
                                    gchar **str_return,
                                    gsize *length,
                                    GError **error);
GIOStatus g_io_channel_write_chars (GIOChannel *channel,
                                    const gchar *buf,
                                    gssize count,
                                    gsize *bytes_written,
                                    GError **error);
サーバプログラム

input_event サンプルでは,「クライアントウィンドウ上で起こったイベント」を,そのままサーバに送っています.(GdkEvent構造体そのものを,バイナリデータとして送受信します)

  • チャネルの作成と追加
  • my_input_event_server
  /* サーバソケットを作成 */
  if((s_in = ServerSetup(portnumber)) < 0) {
    return make_error_message("Error: ServerSetup");
  }
  /* ソケットに関数を結び付けメイン・イベント・ループに追加 */
  if(!add_watch(s_in, (GIOFunc)read_client, g_drawable)) {
    return make_error_message("Error: AddWatch"); 
  }
  • add_watch
  /* ソケットからIOチャネルを作成 */
  channel = g_io_channel_unix_new(sin);
  /* チャネルがなくなるときソケットも閉じる */
  g_io_channel_set_close_on_unref(channel, TRUE);
  /* チャネルの送受信データのエンコードをなし(バイナリ用)に
     デフォルトはUTF-8 */
  g_io_channel_set_encoding(channel, NULL, NULL);
  /* チャネルを非ブロックモードに */
  g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, &error);

  /* メイン・イベント・ループにチャネル channel に
     データが届いたり(G_IO_IN)、ハングアップ(G_IO_HUP)したら
     関数 func を data を引数として呼び出すように登録 */
  g_io_add_watch(channel, G_IO_IN | G_IO_HUP, func, data);
  • チャネルの使用
  • read_client
  status = g_io_channel_read_chars(channel, (gchar *)&event, sizeof(event), &size, &error);
  switch(status) {
    case G_IO_STATUS_NORMAL:
      /* 読み込み正常 */
      /* 何かやりたいことを書く */
      return TRUE;
    case G_IO_STATUS_ERROR:
      /* 読み込み失敗 */
      g_printerr("Error reading fd from client: %s\n", error->message);
      /* この関数をループから外す */
      return FALSE;
    default:
      return FALSE;
  }


最終更新日:2017/04/03 09:14:22