ROS-I simple_message 源码分析:TcpSoc
2019-03-22 本文已影响0人
play_robot
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。