【问题标题】:Multithreaded TCP server on background thread- how to force close from main thread后台线程上的多线程 TCP 服务器 - 如何从主线程强制关闭
【发布时间】:2017-11-09 06:30:55
【问题描述】:

我有 GUI 应用程序,这个应用程序通过调用来启动服务器 start_server() 函数。然后在服务器循环中创建 TCP 被动套接字接收传入连接(我们这里有连接套接字)并同时在多个线程上处理它们。

现在我需要一些 end_server() 函数来强制关闭服务器和所有连接。关闭此类服务器的最佳做法是什么。

我考虑这样做:

  1. 传递给start_server()函数一些server_info_t结构。
  2. 那么当被动套接字创建时,它的描述符 i 存储在 server_info_t 中,也存储了它的绑定端口号
  3. server_info_t 结构中有on_server_start 回调,它在服务器被正确创建后被异步调用,返回一些关于创建的服务器的信息,比如服务器正在侦听的端口号(这可以改变GUI controls,比如状态图标从红到绿)
  4. 然后我传递相同的结构server_info_t info server_loop,在那里,来自客户端的新连接即将到来,我将使用连接套接字并将其描述符存储在 server_info_t 结构中一些linked_list_t 或 hash_map_t 的连接套接字。
  5. 现在我可以调用一些异步回调,如on_client_connected,并将连接(连接套接字)的处理传递给另一个函数(从线程池中分离线程),然后服务器循环等待下一个连接。我还需要在此处传递server_info_t 结构,以从 linked_list 的 conn 套接字描述符中删除 connection_socket 描述符,它为给定的客户端 完成 连接处理
  6. struct server_info 里面可以有另一个回调函数on_client_disconnected
  7. 现在在后台运行的这个多线程服务器之外,我有一个启动服务器的 GUI 应用程序,它具有指向 server_info_t 结构的指针,该结构存储有关服务器的所有信息:端口号、被动套接字、实际连接的连接套接字的linked_list(活动套接字),应调用的回调函数指针以通知服务器事件等。 所以我想我可以创建end_server(server_info_t)(例如,当用户在GUI 应用程序 用户界面中单击STOP 时),奇迹发生了……服务器停止。但是怎么做?

我是否应该获取所有连接套接字(在迭代 server_info_t 结构中的链表时)并使用 (shutdown + close) 关闭它们,然后关闭 + 关闭被动套接字?

然后我什至可以调用一些回调 on_server_end 我在 server_info_t 结构中找到的指针。

我应该使用一些互斥锁来同步访问这个 server_info_t 结构吗?

【问题讨论】:

  • 这是关于 windows 的吗?作为第一个提示,永远不要调用你自己的类型something_t_t 后缀保留用于在任何 POSIX 环境中(编译器/标准库/...)的实现。
  • 它相当 unix。我将在我的 macOS GUI 应用程序以及带有 cygwin 的 Windows 上使用它。
  • 你可能应该为每个线程设置一些信号变量来通知线程关闭请求然后等待它(例如pthread_join()使用 POSIX 线程)。也许您应该澄清平台显示您的一些代码以获得实际的答案
  • 它是 Objective-c 中的 cocoa 应用程序,我尝试用 C 为它编写跨平台的服务器(也可在 Windows 上使用)
  • linux.die.net/man/3/pthread_cond_signal 你是这个意思吗?

标签: c multithreading sockets tcp server


【解决方案1】:

我应该使用一些互斥锁来同步访问这个 server_info_t 结构吗?

您绝对应该同步对共享数据结构的访问。

我是否应该获取所有连接套接字(在迭代 server_info_t 结构中的链表时)并使用 (shutdown + close) 关闭它们,然后关闭 + 关闭被动套接字?

这是一种快速而肮脏的解决方案。更好的设计是通知工作线程应该关闭连接。在这种情况下,您可以:

  • 通知服务器客户端连接关闭的原因
  • 当前请求的完整过程

解决“通知”任务的方法可以不同:

  • 如果你使用select/poll/epoll方法你可以使用指定的socket(例如socketpair)来表示停止
  • 如果您使用阻塞调用,您可以使用pthread_cancel 机制,但它们非常依赖于系统
  • 如果您的工作线程定期唤醒,您可以使用某种原子标志

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-02
    • 2011-07-03
    • 2018-01-23
    • 1970-01-01
    相关资源
    最近更新 更多