ROS-I simple_message 源码分析:TcpServer

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就完成了。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 最近在学习Python看了一篇文章写得不错,是在脚本之家里的,原文如下,很有帮助: 一、网络知识的一些介绍 soc...
    qtruip阅读 2,852评论 0 6
  • 网络编程 一.楔子 你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运...
    go以恒阅读 2,270评论 0 6
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,783评论 1 32
  • 说明 本文 翻译自 realpython 网站上的文章教程 Socket Programming in Pytho...
    keelii阅读 2,467评论 0 16
  • 1、a今天我主持早会,看到翻译不在我就想我今天应该主动出击来当翻译,年头升起时我觉察到自己全身紧张,脑袋全是负面不...
    我是一面镜子阅读 156评论 0 0

友情链接更多精彩内容