我正在用C语言编写一个聊天程序,使用c socket编程和gtk+作为GUI.我有两个程序的变体,分别运行在两台计算机上,一个变体有客户端的代码,另一个有服务器端的代码,两者都有相同的GUI和相同的用户功能选项。
我的程序在客户端是GUI,而服务器没有GUI的情况下也能运行,但是,当我尝试启用服务器的GUI时,客户端仍然可以连接到服务器,但是由于某些原因,消息似乎无法通过。
我使用了glade,它是一个很容易创建GUI的软件,所以语法与gtk有点不同,但它使用gtk,所以应该是一样的,我的服务器GUI的主要功能是这样的。
int main(int argc, char *argv[])
{
//GtkBuilder *builder;
GtkWidget *window;
//creating a widgets from type app_widgets
app_widgets *widgets = g_slice_new(app_widgets);
//GtkTextIter iter;
//creating gtk_init
gtk_init(&argc, &argv);
printf("creating gtk_init successfully");
//using gtk_builder to create the graphics for the gui using glade
builder = gtk_builder_new_from_file("glade/window_main.glade");
//binding the builder to the main container
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
// Get pointers to widgets
//pointer to the main text view where chat is shown
widgets->w_txtvw_main = GTK_WIDGET(gtk_builder_get_object(builder, "txtview_main"));
//pointer to main text buffer that displays the chat
widgets->textbuffer_main = GTK_TEXT_BUFFER(gtk_builder_get_object(builder, "textbuffer_main"));
//pointer to text buffer where user can type msgs for server
widgets->textbuffer_type = GTK_TEXT_BUFFER(gtk_builder_get_object(builder, "textbuffer_type"));
//connecting the widgets to signal to the builder
gtk_builder_connect_signals(builder, widgets);
//gtk_widget_show is called once done setting up widget settings
gtk_widget_show(window);
//start client side
//connecting to sock
sock = startServer();
printf("sock: %d", sock);
if(sock < 0) {
printf("PROGRAM ERROR: Client did not launch!\n");
exit(0);
}
int valListen = listenToSock(sock);
printf("valListen: %d\n", valListen);
if(valListen == -1) {
printf("PROGRAM ERROR: Server failed listening to socket");
printf("Please Relaunch the Application!");
exit(0);
}
printf("sock: %d", sock);
/*
//validating key generation
int valKey = getKey(keyP);
//once password was entered successfully, check will be changed to 1
int check = 0;
if(valKey < 0) {
printf("PROGRAM ERROR: password hashed did not hash successfully");
exit(0);
}
*/
//currReceive is the status of the received data, if equal to 1 than data received,
int currReceive = 0;
//bufOutput is the data received
char bufOutput[] = "";
//pointer to bufOutput
char * bOP = bufOutput;
//using a while loop for gtk_main_iteration
//using gtk_main_iteration() instead of gtk_main() because i need to receive msgs while gui works - need to handle a few events
while (1==1) {
//runs 1 iteration of main loop
gtk_main_iteration();
//checking if received data
currReceive = receive(bOP, sock, key, valQ);
//currReceive = 1 if data was received
if(currReceive == 1) {
//printing msg in cmd
printf("\nMessage: %s<\n", bOP);
//updating the main buffer for viewing chat with the new msg received
update_main_viewedit(widgets, bOP, "Server: ");
}
//if receiving failed, quit
if(currReceive == -1) {
printf("PROGRAM ERROR: Receiving from server failed");
on_window_main_destroy();
return -1;
}
}
//free widgets memory
g_slice_free(app_widgets, widgets);
return 0;
}
接收功能工作正常,因为我已经在GUI之外进行了测试,还运行了一个简单的函数来测试接收和发送功能,它们无缝地工作:简单的函数看起来像这样。
void communicateUsingFunctions(int sock) {
int valid;
char info[MAX];
char * send = info;
while(1 == 1) {
valid = receive(send, sock, 3, 0);
if(valid == 1) {
printf("Message From Functions: %s", send);
sendToClient(send, sock, "dsad");
}
}
}
我很想得到一些帮助,因为我不知道为什么它不能工作, 接收和发送功能都能在对方的图形用户界面上正常工作。
谢谢大家的贡献!
你真的不应该试图把你自己的手卷的 while (TRUE)
循环,而不是GTK正在使用的事件循环(也就是GMainLoop),通过调用 gtk_main_iteration()
. 还请注意,文档中甚至明确提到这是一个阻塞调用。
如果没有事件等待处理,GTK就会阻塞,直到下一个事件被发现。
人们试图做一些像这样的有趣的事情,这也是为什么会有 gtk_main*()
从GTK4中删除了(改为只使用 GtkApplication
). 所以这个。
//using gtk_main_iteration() instead of gtk_main() because i need to receive msgs while gui works - need to handle a few events
并不是一个真正的好办法,必须并发运行东西。
关于如何实际解决这个问题:在GLib中,有很多方法可以调用异步代码,这样就不会阻塞主线程(UI运行的地方),其实主线程也很好的集成在主循环中。比如说,请看