美文网首页
ROS-I simple_message 源码分析:UdpCli

ROS-I simple_message 源码分析:UdpCli

作者: play_robot | 来源:发表于2019-03-22 18:13 被阅读0次

    UdpClient继承自UdpSocket,实现了一个UDP客户端

    namespace industrial
    {
    namespace udp_client
    {
    
    class UdpClient : public industrial::udp_socket::UdpSocket
    {
    public:
    
      UdpClient();
      ~UdpClient();
    
      bool makeConnect();
      bool init(char *buff, int port_num);
    };
    
    } //udp_server
    } //industrial
    
    init
    bool UdpClient::init(char *buff, int port_num)
    {
      int rc;
      bool rtn;
      addrinfo *result;
      addrinfo hints = {};
    
      /* Create a socket using:
       * AF_INET - IPv4 internet protocol
       * SOCK_DGRAM - UDP type
       * protocol (0) - System chooses
       */
      rc = SOCKET(AF_INET, SOCK_DGRAM, 0);
      if (this->SOCKET_FAIL != rc)
      {
        this->setSockHandle(rc);
    
        // Initialize address data structure
        memset(&this->sockaddr_, 0, sizeof(this->sockaddr_));
        this->sockaddr_.sin_family = AF_INET;
    
        // Check for 'buff' as hostname, and use that, otherwise assume IP address
        hints.ai_family = AF_INET;  // IPv4
        hints.ai_socktype = SOCK_DGRAM;  // UDP socket
        hints.ai_flags = 0;
        hints.ai_protocol = 0;
        hints.ai_canonname = NULL;
        hints.ai_addr = NULL;
        hints.ai_next = NULL;
        if (0 == GETADDRINFO(buff, NULL, &hints, &result))
        {
          this->sockaddr_ = *((sockaddr_in *)result->ai_addr);
        }
        else
        {
          this->sockaddr_.sin_addr.s_addr = INET_ADDR(buff);
        }
        this->sockaddr_.sin_port = HTONS(port_num);
    
        rtn = true;
    
      }
      else
      {
        LOG_ERROR("Failed to create socket, rc: %d", rc);
        rtn = false;
      }
      return rtn;
    }
    

    init完成了下一步进行连接所需的socket参数:用户传进来的IP地址和端口号转换为socket数据结构。

    makeConnect
    bool UdpClient::makeConnect()
    {
      ByteArray send;
      char sendHS = this->CONNECT_HANDSHAKE;
      char recvHS = 0;
      bool rtn = false;
      const int timeout = 1000;  // Time (ms) between handshake sends
      int bytesRcvd = 0;
      
      if (!this->isConnected())
      {
        this->setConnected(false);
        send.load((void*)&sendHS, sizeof(sendHS));
      
        const int sendLen = send.getBufferSize();
        char      localBuffer[sendLen];
        send.unload(localBuffer, sendLen);
    
        do
        {
          ByteArray recv;
          recvHS = 0;
          LOG_DEBUG("UDP client sending handshake");
          this->rawSendBytes(localBuffer, sendLen);
          if (this->isReadyReceive(timeout))
          {
            bytesRcvd = this->rawReceiveBytes(this->buffer_, 0);
        LOG_DEBUG("UDP client received possible handshake");    
            recv.init(&this->buffer_[0], bytesRcvd);
            recv.unload((void*)&recvHS, sizeof(recvHS));
          }
        }
        while(recvHS != sendHS);
        LOG_INFO("UDP client connected");
        rtn = true;
        this->setConnected(true);
        
      }
      else
      {
        rtn = true;
        LOG_WARN("Tried to connect when socket already in connected state");
      }
    
      return rtn;
    }
    

    客户端的makeConnect逻辑与服务器端相反,先发送握手号,再接收服务器回复的握手号,两者相等则表明“连接”建立。

    至此已经分析完了simple message的所有模块,这为我们编写ROS端的client nodes和控制器端的server打下了坚实的基础。

    相关文章

      网友评论

          本文标题:ROS-I simple_message 源码分析:UdpCli

          本文链接:https://www.haomeiwen.com/subject/hvwrvqtx.html