GMainLoop 和 TCP Listen 线程阻塞

GMainLoop and TCP Listen thread blocking

本文关键字:线程 Listen TCP GMainLoop      更新时间:2023-10-16

我需要你的帮助。

我有主循环 GMainLoop,附加了超时回调:

MainLoop = g_main_loop_new(NULL, FALSE);
g_timeout_add_seconds(Interval, TimeoutCallback, (gpointer) Rec);
g_main_loop_run(MainLoop);

并收听套接字:

int ControlServer::GStart()
 {
   int listenfd;
   GIOChannel *in;
   socklen_t addr_len;
   listenfd = TcpListen(host, port, &addr_len);
   in = g_io_channel_unix_new(listenfd);
   g_io_add_watch(in, G_IO_IN, (GIOFunc) Handler, (gpointer) Rec);
   g_io_channel_unref(in);
   return 0;
 }

一切都很好,超时功能正常工作,直到任何客户端未连接到侦听的套接字。连接后,超时在客户端连接时不起作用。我认为它与线程相连,因为默认情况下 GMainContext 中的所有操作都在一个线程中执行。我用这个修改了代码:

int ControlServer::GThStart()
 {
  int listenfd;
  socklen_t addr_len;
  GIOChannel *Channel;
  GSource *Source;
  GMainContext *Context;
  listenfd = TcpListen(host, port, &addr_len);
  Channel = g_io_channel_unix_new(listenfd);
  Source = g_io_create_watch(Channel, G_IO_IN);
  g_source_set_callback(Source, (GSourceFunc) Handler, (gpointer) Rec, NULL);
  Context = g_main_context_new();
  g_source_attach(Source, Context);
  g_source_unref(Source);
  return 0;
}

但是现在套接字被侦听,但没有任何客户端可以连接到它,并且从未调用过处理程序函数。

处理程序代码如下:

bool ControlServer::Handler(GIOChannel *in, GIOCondition condition, gpointer data)
 {
   Recorder *Rec = (Recorder *) data;
   struct sockaddr_storage income;
   int insock, newsock;
   socklen_t income_len;
   struct sockaddr peer;
   socklen_t size;
   Access *access;
   insock = g_io_channel_unix_get_fd(in);
   income_len = sizeof(income);
   newsock = accept(insock, (struct sockaddr *) &income, &income_len);
   size = sizeof(peer);
   getpeername(newsock, &peer, &size);
   struct sockaddr_in *ipv4 = (struct sockaddr_in *) &peer;
   access = new Access(newsock, ipv4, MAXN);
   access->Cycle(Rec);
   delete access;
   return true;
}

类"访问"检查客户端的权限,并在客户端或服务器未关闭连接时通过实现无限循环执行协议交换。

  do
    {
      result = DoCycle(Rec);
      sprintf(str, "DEBUG: DoCycle(Rec) returns '%d'n", result);
      AppendLog(str, class_name, DEBUG);
    } while (result != -1);

DoCycle() 仅在连接关闭或通过 TCP 交换数据时出错时才返回"-1"。

怎么了?谢谢!

问题出在函数int ControlServer::GThStart(),您应该将GSource添加到GMainLoopGMainContext,而不是新的上下文,请尝试使用:

g_source_attach(Source,g_main_loop_get_context(MainLoop));