具有接收/发送命令和请求/响应设计的 C++ 服务器

标签 c++ server send recv winsockets

我正在尝试创建一个带有阻塞套接字的服务器(每个新客户端一个新线程)。该线程应该能够从客户端接收命令(并发送回结果)并定期向客户端发送命令(并请求返回结果)。
我的想法是为每个客户端创建两个线程,一个用于 recv , 第二为 send .然而:

  • 它是正常线程开销的两倍。
  • 由于请求/响应设计,我在第一个线程中执行的recv(等待客户端的命令)可以是我在第二个线程中查找的请求(客户端的结果到我的发送),反之亦然。使所有内容正确同步可能是一个 hell 般的故事。所以现在我想用这种方式从一个线程中做到这一点:

  • 在一个循环中:
  • setsockopt(SO_RCVTIMEO, &small_timeout);//设置recv的超时时间(比如1000毫秒)。
  • recv();//首先检查客户端的请求。如果返回 WSAETIMEDOUT 比我假设没有数据被请求并且什么都不做。如果我收到一个正常的请求,我会处理它。
  • if (clientbufferToSend != nullptr) send(clientbufferToSend);//现在,当客户端的请求被处理后,我们检查我们必须发送给客户端的命令列表。如果队列中有命令,我们发送它们。 SO_SNDTIMEO 超时可以设置为一个很大的值,这样如果客户端失去连接我们就不会死锁。
  • setsockopt(SO_RCVTIMEO, &large_timeout);//设置recv的超时时间(和SO_SNDTIMEO一样大,只是为了不死锁,如果有的话)。
  • recv();//现在我们等待来自客户端的响应。


  • 这是做我想做的事情的合法方式吗?还是有更好的选择(最好是阻塞套接字和线程)?
    附言是否 recv()超时返回 WSAETIMEDOUT只有在没有数据可用的情况下?有数据能不能返回这个错误,但是recv()处理这一切的速度不够快,因此返回了部分数据?

    最佳答案

    一种方法是只创建一个后台线程来读取该套接字。写在你的不请自来的事件引发的任何随机线程上。
    你需要以下东西。

  • 每个套接字的关键部分或互斥锁用于序列化写入,例如当后台线程正在发送对客户端发起的消息的响应时,并且其他线程想要将消息发送到同一个客户端。
  • 其他一些同步原语,例如客户端线程在等待响应时休眠的条件变量。
  • 接收消息的后台线程需要区分客户端发起的消息(需要由同一个后台线程响应)和对服务器发起的消息的响应。如果您的网络协议(protocol)没有该数据,您将不得不更改协议(protocol)。

  • 如果您的服务器启动的事件仅发生在单个线程上,这将正常工作,例如它们来自一些序列化的源,如设备或操作系统接口(interface)。
    但是,如果事件源也是多线程的,并且您希望获得良好的性能,那么您将需要不平凡的复杂性来将响应分派(dispatch)到正确的服务器线程,例如每个客户端线程 1 个条件变量,可能还有一些队列等。

    关于具有接收/发送命令和请求/响应设计的 C++ 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63092958/

    相关文章:

    c++ - 二叉搜索树插入数据问题

    c# - 如何将(和 Marshall)CityHash std::pair<uint64,uint64> 从 C# 转换为 C++,反之亦然

    linux - SSH 连接到远程服务器上的 GitHub

    r - Shiny 的应用程序错误 :/v1/applications/400 - Validation Error Execution halted

    javascript - Localhost 拒绝来自 Javascript 的连接

    c++ - 在两个方向上寻找搜索算法 - c/c++/awk

    c# - 使用 .NET 发送电子邮件 - 不那么容易

    css - 导致水平滚动的 Facebook 发送按钮

    python阻塞套接字,发送立即返回

    c++ - 获取指向 boost::any 内容的 void* 指针