由gio库实现的简单线程服务器

时间:2015-08-26 10:37:44

标签: c server iostream gio

我正在尝试学习gio库,尤其是giostream和gthreadedsocketservice。我想写一个简单的服务器:

  1. 每个传入连接将由单独的新线程处理
  2. 在客户端,用户键入一个字符串,然后将其发送到服务器;收到字符串后,在服务器端立即将其显示给stdout。
  3. 除非服务器或客户端终止,否则连接不会关闭。即,可以从客户端向服务器发送多条消息,而无需多次连接。
  4. 我尝试的代码是: 客户端:

    #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;
    }
    

    服务器端:

    #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;
    }
    

    问题是当我测试它时,在客户端我键入了三行:

    aaa
    bbb
    ccc
    

    但是服务器端没有显示任何内容。只有当我退出客户端时,它才会在服务器屏幕上显示:

    aaabbbccc
    

    但我想要的是当我输入&#34; aaa&#34;并输入,它立即显示在服务器屏幕上。

    知道哪里出错了?

1 个答案:

答案 0 :(得分:1)

问题是你使用g_input_stream_read_all。请注意名称中的后缀all?这意味着它将尝试读取您传递给它的大小,仅在收到所有那些字节或者出现错误或断开连接时返回。

而是使用例如循环中g_input_stream_read