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

ROS-I simple_message 源码分析:TcpSer

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

    TcpServer类继承自TcpSocket,提供了server的初始化和连接功能。

    namespace industrial
    {
    namespace tcp_server
    {
    
    class TcpServer : public industrial::tcp_socket::TcpSocket
    {
    public:
    
      TcpServer();
      ~TcpServer();
    
      bool init(int port_num);
    
      // Overrides
      bool makeConnect();
    
    protected:
    
      int srvr_handle_;
    
      int getSrvrHandle() const
      {
        return srvr_handle_;
      }
    
      void setSrvrHandle(int srvr_handle_)
      {
        this->srvr_handle_ = srvr_handle_;
      }
    };
    
    } //simple_socket
    } //industrial
    
    init
    bool TcpServer::init(int port_num)
    {
      int rc;
      bool rtn;
      const int reuse_addr = 1;
      //int err;
      SOCKLEN_T addrSize = 0;
    
      rc = SOCKET(AF_INET, SOCK_STREAM, 0);
      if (this->SOCKET_FAIL != rc)
      {
        this->setSrvrHandle(rc);
        LOG_DEBUG("Socket created, rc: %d", rc);
        LOG_DEBUG("Socket handle: %d", this->getSrvrHandle());
    
        
        SET_REUSE_ADDR(this->getSrvrHandle(), reuse_addr);
    
        // Initialize address data structure
        memset(&this->sockaddr_, 0, sizeof(this->sockaddr_));
        this->sockaddr_.sin_family = AF_INET;
        this->sockaddr_.sin_addr.s_addr = INADDR_ANY;
        this->sockaddr_.sin_port = HTONS(port_num);
    
        addrSize = sizeof(this->sockaddr_);
        rc = BIND(this->getSrvrHandle(), (sockaddr *)&(this->sockaddr_), addrSize);
    
        if (this->SOCKET_FAIL != rc)
        {
          LOG_INFO("Server socket successfully initialized");
    
          rc = LISTEN(this->getSrvrHandle(), 1);
    
          if (this->SOCKET_FAIL != rc)
          {
            LOG_INFO("Socket in listen mode");
            rtn = true;
          }
          else
          {
            LOG_ERROR("Failed to set socket to listen");
            rtn = false;
          }
        }
        else
        {
          LOG_ERROR("Failed to bind socket, rc: %d", rc);
          CLOSE(this->getSrvrHandle());
          rtn = false;
        }
    
      }
      else
      {
        LOG_ERROR("Failed to create socket, rc: %d", rc);
        rtn = false;
      }
    
      return rtn;
    }
    

    init方法用于TCP server的初始化,依次调用socket创建套接字,调用bind绑定地址,最后调用listen启动服务端的监听,等待客户端的连接请求。
    this->setSrvrHandle(rc)用于将创建好的监听socket描述符保存至本地,以便将来恢复连接时使用。

    makeConnect
    bool TcpServer::makeConnect()
    {
      bool rtn = false;
      int rc = this->SOCKET_FAIL;
      //int socket = this->SOCKET_FAIL;
      int disableNodeDelay = 1;
      int err = 0;
    
      if (!this->isConnected())
      {
        this->setConnected(false);
        if (this->SOCKET_FAIL != this->getSockHandle())
        {
          CLOSE(this->getSockHandle());
          this->setSockHandle(this->SOCKET_FAIL);
        }
    
        rc = ACCEPT(this->getSrvrHandle(), NULL, NULL);
    
        if (this->SOCKET_FAIL != rc)
        {
          this->setSockHandle(rc);
          LOG_INFO("Client socket accepted");
    
          // The set no delay disables the NAGEL algorithm
          rc = SET_NO_DELAY(this->getSockHandle(), disableNodeDelay);
          err = errno;
          if (this->SOCKET_FAIL == rc)
          {
            LOG_WARN("Failed to set no socket delay, errno: %d, sending data can be delayed by up to 250ms", err);
          }
          this->setConnected(true);
          rtn = true;
        }
        else
        {
          LOG_ERROR("Failed to accept for client connection");
          rtn = false;
        }
      }
      else
      {
        LOG_WARN("Tried to connect when socket already in connected state");
      }
    
      return rtn;
    
    }
    

    makeConnect用于接受客户端连接请求,由accept函数完成。并保存连接socket描述符,以备和客户端之间的发送接收时使用。至此,一个可用的TcpServer就完成了。

    相关文章

      网友评论

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

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