c++ - 关于多线程UDP Client-Server架构的问题

标签 c++ multithreading sockets udp

我正在练习一些套接字和 UDP 客户端-服务器架构,引用网上的一些示例,我已经使用 C 实现了一个非常简单的 UDP 服务器,并使用 C++ 实现了 UDP 客户端类。
简而言之,当前的实现让服务器监听传入的消息并将相同的数据包传回客户端。
如果客户端发出顺序请求,它似乎工作正常。
这是一个简短的解释性示例:

#include "UDPClient.h"
int main(int argc, char* argv[]) {
  UDPClient testClient;
  testClient.initSockets(1501, "127.0.0.1", 1500);
  for (int i = 0; i < 10; i++) {
    testClient.notifyEntry();
    testClient.notifyExit();
  }
  return 0;
}

由于客户端实际上应该同时与服务器共享更多信息,所以我测试了启动新线程的相同代码块:

#include <thread>
#include "UDPClient.h"
int main(int argc, char* argv[]) {
  UDPClient testClient;
  std::thread thrdOne, thrdTwo;
  testClient.initSockets(1501, "127.0.0.1", 1500);
  for (int i = 0; i < 10; i++) {
    thrdOne = std::thread(UDPClient::notifyEntry, std::ref(testClient));
    thrdTwo = std::thread(UDPClient::notifyExit, std::ref(testClient));
  }
  return 0;
}

如您所见,notifyEntrynotifyExit 已变为 static,目前需要引用类实例才能正常工作。 此外,在它们的函数体内,我还添加了一个小代码块,以检查由于服务器发回相同的内容,发送的消息是否等于接收的消息。
这是一个解释性示例:

void UDPClient::notifyEntry(UDPClient& inst) {
  char buffer = "E"
  inst.sendPacket(buffer);  // sendto...
  inst.receivePacket(buffer);  // recvfrom...
  if (!(buffer == 'E') ){
    std::string e = "Buffer should be E but it is ";
    e.append(buffer);
    throw UDPClientException(e);
  }
}

使用多线程经常会发生上面提到的检查抛出异常,因为缓冲区实际上包含另一个char(notifyExit发送的那个)。

考虑到这些信息,请问您:

  1. 发生这种情况是因为线程的 recvfrom 也可以捕获来自另一个线程的请求的响应,而套接字实例化只是一个绑定(bind)套接字?
  2. 如果是,我是否应该实例化多个套接字(例如,每个套接字只能用于一种类型的消息,一个用于 notifyEntry,一个用于 notifyExit)?服务器上的多线程仅用于响应是否不能解决所提到的问题?

最佳答案

this happens because the recvfrom of a thread can catch also the response of a request from another one, being the socket instantiated only a single bound socket?

这很有可能——如果您有多个线程在同一个 UDP 套接字上调用 recvfrom(),那么哪个线程接收哪个传入的 UDP 数据包将是不确定的/不可预测的。

if yes, should I instantiate more than a single socket (for instance, each one usable for only a single type of messages, that is one for notifyEntry and one for notifyExit)?

是的,我建议让每个线程创建自己的私有(private) UDP 套接字并将其套接字 bind() 到它自己的单独端口(例如,将 0 作为端口号传递给 bind()) ;这样每个线程都可以确保只接收自己的响应,而不会被其他线程的响应所混淆。 (请注意,您还需要对服务器进行编码,以将其回复发送回 recvfrom() 调用报告的 IP 地址和端口,而不是将回复数据包发送回硬-编码端口号)

Does multithreading on server for response only not solve the issue mentioned anyway?

不,正确处理(或不正确处理)UDP 数据包是一个单独的问题,与服务器是单线程还是多线程无关。

关于c++ - 关于多线程UDP Client-Server架构的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54380525/

相关文章:

具有共享 vptr 的多态对象的 C++ 容器

c++ - 调用外部脚本时的奇怪行为

java - 阻塞方法引起的死锁

Java客户端-服务器问题

java - 从 HTTP 服务器中的套接字读取的推荐方法

c++ - 编译时检查函数是否被使用/未使用 c++

c++ - 使用指向 STL vector 的指针是个好主意吗?

c++ - 如何将 Crypto++ 库移植到 AIR Native Extension for Windows?

Java - 等待最长时间或事件(异步回调),以先到者为准

c - 套接字编程——connect()中参数的含义