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

ROS-I simple_message 源码分析:TcpSoc

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

TcpSocket类继承自SimpleSocket

namespace industrial
{
namespace tcp_socket
{

class TcpSocket : public industrial::simple_socket::SimpleSocket
{
public:

  TcpSocket();
  virtual ~TcpSocket();

private:

  // Virtual
  int rawSendBytes(char *buffer,
      industrial::shared_types::shared_int num_bytes);
  int rawReceiveBytes(char *buffer,
      industrial::shared_types::shared_int num_bytes);
  bool rawPoll(int timeout, bool & ready, bool & error);

};

} //tcp_socket
} //industrial
rawSendBytes
int TcpSocket::rawSendBytes(char *buffer, shared_int num_bytes)
{
  int rc = this->SOCKET_FAIL;

  rc = SEND(this->getSockHandle(), buffer, num_bytes, 0);
  
  return rc;
}

SEND由宏定义给出,Linux平台对应的是系统调用send函数,现在终于已经看到了simple_message package的通信底层了。

//Linux平台
#define SEND(sockfd, buf, len, flags)   send(sockfd, buf, len, flags)
rawReceiveBytes
int TcpSocket::rawReceiveBytes(char *buffer, shared_int num_bytes)
{
  int rc = this->SOCKET_FAIL;
  
  rc = RECV(this->getSockHandle(), buffer, num_bytes, 0);
  
  return rc;
}

RECV由宏定义给出,Linux平台对应的是系统调用recv函数:

#define RECV(sockfd, buf, len, flags) recv(sockfd, buf, len, flags)
rawPoll
bool TcpSocket::rawPoll(int timeout, bool & ready, bool & error)
{
  timeval time;
  fd_set read, write, except;
  int rc = this->SOCKET_FAIL;
  bool rtn = false;
  ready = false;
  error = false;

  // The select function uses the timeval data structure
  time.tv_sec = timeout / 1000;
  time.tv_usec = (timeout % 1000) * 1000;

  FD_ZERO(&read);
  FD_ZERO(&write);
  FD_ZERO(&except);

  FD_SET(this->getSockHandle(), &read);
  FD_SET(this->getSockHandle(), &except);

  rc = SELECT(this->getSockHandle() + 1, &read, &write, &except, &time);

  if (this->SOCKET_FAIL != rc) {
    if (0 == rc)
      rtn = false;
    else {
      if (FD_ISSET(this->getSockHandle(), &read)) {
        ready = true;
        rtn = true;
      }
      else if(FD_ISSET(this->getSockHandle(), &except)) {
        error = true;
        rtn = true;
      }
      else {
        LOG_WARN("Select returned, but no flags are set");
        rtn = false;
      }
    }
  } else {
    this->logSocketError("Socket select function failed", rc, errno);
    rtn = false;
  }
  return rtn;
}

rawPoll这个方法实现了socket的状态查询,即是否可读或存在错误异常,并提供超时参数设置接口,提供给数据接收方法调用。利用的是Linux系统调用select实现的查询功能,这样的好处就是在数据接收时程序不会持续性阻塞,上层可以以轮询的方式完成数据接收功能。

#define SELECT(n, readfds, writefds, exceptfds, timeval) select(n, readfds, writefds, exceptfds, timeval)

TcpSocket这个类还不能直接提供给上层使用,它还没有提供具体的显式连接、断开连接服务,因此还需要再做一层封装,这就是下面要分析的TcpServer,TcpClient。

相关文章

网友评论

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

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