ROS-I simple_message 源码分析:UdpClient

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 网络编程 一.楔子 你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运...
    go以恒阅读 6,430评论 0 6
  • 一: 网络各个协议:TCP/IP、SOCKET、HTTP 网络七层由下往上分别为物理层、数据链路层、网络层、传输层...
    iYeso阅读 5,275评论 0 13
  • 参考:http://www.2cto.com/net/201611/569006.html TCP HTTP UD...
    F麦子阅读 8,033评论 0 14
  • 计算机网络概述 网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据传输。 按照计算机网络的定义,通过一定...
    蛋炒饭_By阅读 5,002评论 0 10
  • 网络编程 1. 概论 建立连接:通过IP或者域名来连接两台设备,通过端口号找到对应的通信程序 通信协议:要传输的数...
    陵无山阅读 12,449评论 0 12