c++ tcp 多线程客户端/服务器 - 如何与线程 sockethandler 通信?

标签 c++ multithreading tcp udp

<分区>

我用 C++ 制作了一个多线程客户端/服务器。它工作正常。 “协议(protocol)”是基于文本的。我有一个 sockethandler 函数(在无限循环中运行线程,直到连接发生某些事情或客户端优雅地断开连接)在该线程启动后服务器正在等待新连接。现在,对于这个特定的程序,我一次只允许一个客户。到目前为止,客户端一直是发起者,服务器响应。但我需要从其他线程向客户端程序发送大量数据(不是大小、频率),但我不知道该怎么做。我的代码是跨平台的——我从同一来源为 windows 和 linux 编译。客户端/服务器代码是跨平台的,也需要几行...最好的方法是什么?队列?还是有更快的方法?有人可以指出我正确的方向或给我一些示例代码吗? 我确实尝试将其整理出来并在设计方面考虑我正在考虑向客户端添加一个 udp 监听器,向服务器添加一个 udp 发送器,以便我有 2 个通信 channel ,但我不知道这是否是一个好习惯...... 我目前在线程中有一个套接字,但我只知道如何从一个方向使用它 - 这是我的主要问题......

最佳答案

design-wise I'm considering adding an udp listener to the client and an udp sender to the server so that I have 2 communication channels but I don't know if that a good practice...

您可能会遇到的主要问题(除了涉及丢失数据包的常见 UDP 问题之外)是客户端计算机通常会运行一个防火墙来阻止所有传入的 UDP 数据包。如果是这种情况,您需要指示用户禁用防火墙或向防火墙添加规则以允许在您使用的端口上传入 UDP 数据包(这可能是也可能不是合理的请求,具体取决于您的用户)用户是,但肯定会很麻烦)。

鉴于此,如果您可以像往常一样让客户端通过 TCP 连接到服务器,并通过您已经使用的同一 TCP 连接将客户端需要的数据发送回客户端,可能会更好。这样就避免了防火墙问题。

The client/server code is cross platform too give or take a few lines... What's the best method to do this? queues? or are there faster methods? can someone point me in the right direction or give me some example code please?

由于您在评论中指出您的主要问题是跨线程通信,因此这是我在多线程程序中处理该问题的方式:

  1. 我的每个线程都使用非阻塞 I/O 和一个以阻塞调用 select() 为中心的事件循环。这个想法是,线程唯一应该阻塞的地方是 select() 调用,并且只有当线程有更多工作要做时,select() 调用才应该返回。

  2. 为了让线程 A 向线程 B 发送消息,线程 A 必须执行以下操作:

    一个。锁定保护线程 B 的传入消息队列的互斥锁 b.将消息附加到线程 B 的传入消息队列的末尾 C。解锁保护线程 B 的传入消息队列的互斥体 d.向线程 B 发出信号,以便线程 B 唤醒并检查其传入消息队列中是否有新消息

  3. 除了 (d) 部分之外,以上所有内容都很简单——让线程 B 可靠地唤醒。为此,我(在启动时)创建了一个 pipesocket-pair那个线程 A 可以发送到那个线程 B 可以 select() on。因此,作为 (d) 的一部分,线程 A 将一个字节写入其管道末端的套接字(或套接字对),这会导致线程 B 的套接字 select() 为 ready-for-read。当线程 B 看到时,它从套接字中读取字节(当然是非阻塞读取),将它们扔掉,然后锁定其传入消息队列,从该队列中取出所有消息,再次解锁,然后按顺序处理抓取的消息。

请注意,为了保持高效,您可能希望使 Message 对象尽可能零拷贝,尤其是当它们将包含大量数据时。您可以使用 shared_ptr 或类似的方法来做到这一点,这样您添加到队列中的唯一东西就是相对较小的 shared_ptr 对象,而不是它们指向的较大的消息/数据。使用智能指针还可以确保消息/数据不会发生内存泄漏。

这种事情也可能与阻塞 I/O 一起工作,除了如果你使用阻塞 I/O,你将无法保证线程将花费多长时间来响应你发送的消息 --特别是如果存在网络问题,则线程对 TCP 套接字上的 send() 的调用可能在数分钟内不会返回,对此您无能为力——当然,对 recv() 的调用可能会阻塞如果没有来自客户端的数据,则永远。这就是为什么我总是尽可能使用非阻塞 I/O。

关于c++ tcp 多线程客户端/服务器 - 如何与线程 sockethandler 通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36485459/

相关文章:

C 编程 pthread 打印段错误

networking - TCP 状态实现

c++ - 当我尝试绘制 sf::Text 对象时 SFML 中的段错误

c++ - 在 C++ 中使用 std::vector 访问元素(get 和 put)

C++ 删除 [] 崩溃

java - 线程等待直到文件修改

multithreading - 如何在两个线程之间共享或避免共享Websocket资源?

linux - Linux 上通过 TCP 的虚拟串口

java - 通过套接字连续传输数据

c++ - C++ API 设计中的得墨忒耳定律