我用c ++制作了一个多线程客户端/服务器。它工作正常。 '协议'是基于文本的。我有一个sockethandler函数(在无限循环中运行线程,直到连接发生某些事情或客户端正常断开连接)之后该线程启动服务器正在等待新连接。现在,对于这个特定的程序,我一次只允许一个客户端。到目前为止,客户端始终是发起者,服务器响应。但我需要从其他线程向客户端程序发送大量数据(不是大小,频率),我不知道如何。我的代码是跨平台的 - 我从同一个源代码编译windows和linux。客户端/服务器代码是跨平台的,也可以给出几行代码......最好的方法是什么?队列?还是有更快的方法?有人能指出我正确的方向或给我一些示例代码吗? 我确实尝试了解它并且设计明智我考虑将udp监听器添加到客户端并将udp发送器添加到服务器以便我有2个通信通道但是我不知道这是不是很好实践... 我目前在一个帖子中有一个套接字,但我只知道如何从一个方向使用它 - 这是我的主要问题...
答案 0 :(得分:0)
当客户端连接到服务器时,我想在服务器中有一个输入和输出文件。因此,如果您只需要一个共享通信通道,您的客户端可以从服务器中的各种任务访问,那么您应该有一个接收通信并打开通信通道的任务(执行内务处理)。之后你可以使用"共享资源"作为来自每个线程的全局变量,通过使用锁来阻止损坏。
答案 1 :(得分:0)
设计明智我正在考虑向客户端添加udp监听器 udp发送者到服务器,以便我有2个通信通道 但我不知道这是不是一个好习惯......
您可能遇到的主要问题(通常涉及丢弃数据包的UDP问题之外)是客户端计算机通常会运行阻止所有传入UDP数据包的防火墙。如果是这种情况,您需要指示用户禁用防火墙或向防火墙添加规则以允许您正在使用的端口上的传入UDP数据包(这可能是也可能不是合理的请求,具体取决于您的用户是,但肯定是一个麻烦)。
鉴于此,如果您可以让客户端像往常一样通过TCP连接到服务器,并将客户端需要的数据通过您已经使用的相同TCP连接发送回客户端,那可能会更好。这样可以避免防火墙问题。
客户端/服务器代码是跨平台的,也可以是少数 line ...这样做的最佳方法是什么?队列?或者在那里 更快的方法?有人能指出我正确的方向或给我 请问一些示例代码?
因为在评论中你指出你的主要问题是跨线程通信,所以这是我在多线程程序中处理的方式:
我的每个线程都使用非阻塞I / O和一个以select()阻塞调用为中心的事件循环。我们的想法是,线程应该阻塞的唯一位置是select()调用,而select()调用只有在线程有更多的工作时才会返回。
为了让线程A向线程B发送消息,线程A必须执行以下操作:
一个。锁定保护线程B的incoming-Messages-queue的互斥锁 湾将消息附加到线程B的incoming-Messages-queue的末尾 C。解锁保护线程B的incoming-Messages-queue的互斥锁 d。信号线程B,以便线程B将被唤醒并检查其传入消息队列中的新消息
以上所有内容都很简单,除了(d)部分 - 让线程B可靠地唤醒。为此,我创建了(在启动时)线程A可以发送到的pipe或socket-pair,线程B可以选择()。因此,作为(d)的一部分,线程A将一个字节写入管道(或socketpair)末尾的套接字,这会导致线程B的套接字select()为准备读取。当线程B看到它时,它从套接字读取字节(当然是非阻塞读取),将它们抛弃,然后锁定其传入消息队列,从该队列中抓取所有消息,再次解锁,然后按顺序处理抓取的消息。
请注意,为了保持高效,您可能希望尽可能使Message对象为零拷贝,特别是如果它们将包含大量数据。您可以使用shared_ptr或类似方法来执行此操作,以便您添加到队列的唯一内容是相对较小的shared_ptr对象,而不是它们指向的较大的Message / data。使用智能指针还可以确保消息/数据不会泄漏内存。
这种事情也可以用于阻止I / O,除非你使用阻塞I / O,你将无法保证线程响应你发送的消息需要多长时间 - 特别是如果存在网络问题,那么线程对TCP套接字上的send()的调用可能不会在几分钟内返回,并且你无法做很多事情 - 当然调用recv()可能会阻止永远,如果没有来自客户端的数据。这就是为什么我总是尽可能使用非阻塞I / O.