gio 库实现的简单线程服务器
Simple threaded server implemented by gio library
我正在尝试学习 gio 库,尤其是 giostream 和 gthreadedsocketservice。我想写一个简单的服务器:
- 每个传入连接都将由一个单独的新线程处理
- 在客户端,用户输入一个字符串,它会被发送到服务器;在服务器端收到字符串后,立即将其显示到标准输出。
- 除非服务器或客户端终止,否则连接不会关闭。即可以从客户端向服务器发送多条消息,而无需多次连接。
我试过的代码是:
客户端:
#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
但我想要的是当我输入 "aaa" 并输入时,它会立即显示在服务器屏幕上。
知道哪里出了问题吗?
问题是你使用了g_input_stream_read_all
。注意到名称中的后缀 all
了吗?这意味着它将尝试读取您传递给它的大小,只有在它收到 所有 那些字节或者出现错误或断开连接时才会返回。
而是使用例如g_input_stream_read
循环。
我正在尝试学习 gio 库,尤其是 giostream 和 gthreadedsocketservice。我想写一个简单的服务器:
- 每个传入连接都将由一个单独的新线程处理
- 在客户端,用户输入一个字符串,它会被发送到服务器;在服务器端收到字符串后,立即将其显示到标准输出。
- 除非服务器或客户端终止,否则连接不会关闭。即可以从客户端向服务器发送多条消息,而无需多次连接。
我试过的代码是: 客户端:
#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
但我想要的是当我输入 "aaa" 并输入时,它会立即显示在服务器屏幕上。
知道哪里出了问题吗?
问题是你使用了g_input_stream_read_all
。注意到名称中的后缀 all
了吗?这意味着它将尝试读取您传递给它的大小,只有在它收到 所有 那些字节或者出现错误或断开连接时才会返回。
而是使用例如g_input_stream_read
循环。