Enable TCP keepalive on sockets so that we can detect connection "hangs" that can happen when wireless goes out

This commit is contained in:
Josh Faust 2009-12-23 00:20:02 +00:00
parent 46d2b95528
commit 995c8bbba4
3 changed files with 53 additions and 0 deletions

View File

@ -55,6 +55,9 @@ class PollSet;
*/
class TransportTCP : public Transport
{
public:
static bool s_use_keepalive_;
public:
enum Flags
{
@ -95,6 +98,7 @@ public:
int getServerPort() { return server_port_; }
void setNoDelay(bool nodelay);
void setKeepAlive(bool use, uint32_t idle, uint32_t interval, uint32_t count);
// overrides from Transport
virtual int32_t read(uint8_t* buffer, uint32_t size);

View File

@ -45,6 +45,7 @@
#include "ros/callback_queue.h"
#include "ros/param.h"
#include "ros/rosout_appender.h"
#include "ros/transport/transport_tcp.h"
#include "roscpp/GetLoggers.h"
#include "roscpp/SetLoggerLevel.h"
@ -266,6 +267,8 @@ void start()
g_started = true;
g_ok = true;
param::param("/tcp_keepalive", TransportTCP::s_use_keepalive_, TransportTCP::s_use_keepalive_);
PollManager::instance()->addPollThreadListener(checkForShutdown);
XMLRPCManager::instance()->bind("shutdown", shutdownCallback);

View File

@ -55,6 +55,8 @@
namespace ros
{
bool TransportTCP::s_use_keepalive_ = true;
TransportTCP::TransportTCP(PollSet* poll_set, int flags)
: sock_(-1)
, closed_(false)
@ -95,6 +97,8 @@ bool TransportTCP::initializeSocket()
}
}
setKeepAlive(s_use_keepalive_, 60, 10, 9);
if (is_server_)
{
cached_remote_host_ = "TCPServer Socket";
@ -144,6 +148,48 @@ void TransportTCP::setNoDelay(bool nodelay)
}
}
void TransportTCP::setKeepAlive(bool use, uint32_t idle, uint32_t interval, uint32_t count)
{
if (use)
{
ROSCPP_LOG_DEBUG("Enabling TCP Keepalive on socket [%d]", sock_);
int val = 1;
if (setsockopt(sock_, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0)
{
ROS_ERROR("setsockopt failed to set SO_KEEPALIVE on socket [%d] [%s]", sock_, cached_remote_host_.c_str());
}
val = idle;
if (setsockopt(sock_, SOL_TCP, TCP_KEEPIDLE, &val, sizeof(val)) != 0)
{
ROS_ERROR("setsockopt failed to set TCP_KEEPIDLE on socket [%d] [%s]", sock_, cached_remote_host_.c_str());
}
val = interval;
if (setsockopt(sock_, SOL_TCP, TCP_KEEPINTVL, &val, sizeof(val)) != 0)
{
ROS_ERROR("setsockopt failed to set TCP_KEEPINTVL on socket [%d] [%s]", sock_, cached_remote_host_.c_str());
}
val = count;
if (setsockopt(sock_, SOL_TCP, TCP_KEEPCNT, &val, sizeof(val)) != 0)
{
ROS_ERROR("setsockopt failed to set TCP_KEEPCNT on socket [%d] [%s]", sock_, cached_remote_host_.c_str());
}
}
else
{
ROSCPP_LOG_DEBUG("Disabling TCP Keepalive on socket [%d]", sock_);
int val = 0;
if (setsockopt(sock_, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0)
{
ROS_ERROR("setsockopt failed to set SO_KEEPALIVE on socket [%d] [%s]", sock_, cached_remote_host_.c_str());
}
}
}
bool TransportTCP::connect(const std::string& host, int port)
{
sock_ = socket(AF_INET, SOCK_STREAM, 0);