ROS-I simple_message 源码分析:UdpCli

2019-03-22  本文已影响0人  play_robot

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打下了坚实的基础。

上一篇下一篇

猜你喜欢

热点阅读