【问题标题】:Create UDP server using C++ to embed in cross platform iOS and Android app使用 C++ 创建 UDP 服务器以嵌入跨平台 iOS 和 Android 应用程序
【发布时间】:2019-10-03 08:51:14
【问题描述】:

我正在使用 cocos2d-x 开发一款跨平台的手机游戏(iOS 和 Android)。 我的大部分代码都是用 C++ 编写的,在 Objective-C / Java / Swift 中使用了特定于操作系统的代码。

我想知道是否有人使用任何 C++ 库在他们的应用程序中托管 UDP 服务器?

编辑:到目前为止,我已经找到了许多特定于平台的解决方案(在 Android 上使用 Java,在 iOS 上使用 cocoaasync 等),但没有专门用于跨平台应用程序的 C++。

编辑:我更喜欢没有提升的解决方案。最好包含一些简单的东西,比如向项目中添加几个文件。

【问题讨论】:

  • 我相信 Boost(谷歌一下,它是一个跨平台的 C++ 库)有 UDP 和 TCP 的套接字版本。
  • libuv 是个不错的选择。

标签: android c++ ios c++11 cocos2d-x


【解决方案1】:

您最有可能使用 Valve 的 GameNetworkingSockets,https://github.com/ValveSoftware/GameNetworkingSockets

它们的外部依赖项非常有限,因此您应该能够为 iOS 和 Android 编译它们

您还可以查看此列表:https://github.com/MFatihMAR/Awesome-Game-Networking,其中有一个您可以尝试的库列表。

【讨论】:

    【解决方案2】:

    您可以使用ASIO Standalone 库。它与boost/asio 是同一个库,但它不需要任何其他boost 库。我在这种类型的项目(Android/iOS)中使用了boost/asio,它是迄今为止最优秀的解决方案。

    【讨论】:

      【解决方案3】:

      这是我最终得到的结果:

      h 文件:

      #include "Queue.h"
      
      #include <sys/types.h>
      #include <sys/socket.h>
      #include <arpa/inet.h>
      #include <netinet/in.h>
      
      #include <array>
      #include <iostream>
      #include <thread>
      
      using namespace std;
      
      #define MAXBUFFER_SIZE 1024
      
      class UDPServer {
      public:
          /**
           * Constructor
           *
           * @port the port on which the UDP server is listening for packets.
           */
          explicit UDPServer(unsigned short port);
      
          /**
           * Destructor
           */
          ~UDPServer() = default;
      
          /**
           * Setup the server.
           */
          void setupServer();
      
          /**
           * Get a single message.
           * For demonstration purposes, our messages is expected to be a array of int
           */
          bool getMessage(std::array<int, 4>& message);
      
          bool getIPAddress(std::array<int, 4>& message);
      
          void setFoundIP();
      
          bool isReady();
      
          void nextPort();
      
          int getPort();
      
      private:
          bool _isBoundToPort = false;
          /**
           * The server port.
           */
          unsigned short port_;
          bool isFoundIP = false;
          /**
           * The thread-safe message queue.
           */
          Queue queue_;
          Queue _ipAddresses;
          /**
           * The UDP server function.
           */
          int UDPServerFunc();
      };
      

      cpp 文件:

      #include "UDPServer.h"
      
      #include <stdio.h>
      #include <unistd.h>
      #include <stdlib.h>
      #include <math.h>
      #include <string.h>
      
      using namespace std;
      
      /**
       * This function parses an incoming message with the following format: 1;234;-89;-53;
       *
       * A valid message consists of 4 integer values separated by semicolons.
       */
      inline std::array<int, 4> parseMessage(const std::string& input);
      inline std::array<int,4> parseIp(const std::string& input);
      
      UDPServer::UDPServer(unsigned short port)   {
          port_ = port;
      }
      
      bool UDPServer::getMessage(std::array<int, 4>& message) {
          return queue_.pop(message);
      }
      
      bool UDPServer::getIPAddress(std::array<int, 4>& message) {
          return _ipAddresses.pop(message);
      }
      
      void UDPServer::setFoundIP(){
          isFoundIP = true;
      }
      
      bool UDPServer::isReady(){
          return _isBoundToPort;
      }
      
      void UDPServer::nextPort(){
          port_++;
      }
      
      int UDPServer::getPort(){
          return port_;
      }
      
      void UDPServer::setupServer() {
          // Launch the server thread.
          std::thread t([this](){
              UDPServerFunc();
          });
          t.detach();
      }
      
      int UDPServer::UDPServerFunc() {
      
          // Creating socket file descriptor
          int sockfd;
          if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
              perror("socket creation failed");
              exit(EXIT_FAILURE);
          }
      
          // Filling server information
          struct sockaddr_in servaddr, cliaddr;
          memset(&servaddr, 0, sizeof(servaddr));
          memset(&cliaddr, 0, sizeof(cliaddr));
          servaddr.sin_family = AF_INET; // IPv
      
          servaddr.sin_addr.s_addr = INADDR_ANY;
          servaddr.sin_port = htons(port_);
      
          // Bind the socket with the server address
          if (::bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
              perror("bind failed");
              exit(EXIT_FAILURE);
          }
      
          _isBoundToPort = true;
          while (true)  {
              // Read the next message from the socket.
              char message[MAXBUFFER_SIZE];
              socklen_t len = sizeof(struct sockaddr);
              ssize_t n = recvfrom(sockfd, (char *)&message, MAXBUFFER_SIZE, MSG_DONTWAIT,
                           (struct sockaddr *)&cliaddr, (socklen_t*)&len);
              if (n > 0) {
                  message[n] = '\0';
                  // Parse incoming data and push the result on the queue.
                  // Parsed messages are represented as a std::array<int, 4>.
      
                  if(!isFoundIP){
                      _ipAddresses.push(parseIp(message));
                  }else{
                      queue_.push(parseMessage(message));
                  }
              } else {
                  // Wait a fraction of a millisecond for the next message.
                  usleep(100);
              }
          }
      
          return 0;
      }
      

      我从我的答案中删除了所有不必要的代码,因为肉实际上就是上面的代码。如果有人也需要额外的功能,我在Github 上分享了代码,稍后也会添加一些示例。

      上面的代码非常简单,并且有几个解析函数来提取一个 IP 地址,或者一组用分号分隔的四个数字。上面的代码很简单,可以根据自己的自定义消息进行修改。

      Queue.h 只是一个简单的线程安全队列。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-26
        • 2011-02-11
        相关资源
        最近更新 更多