Skip to content

Commit 3809d64

Browse files
more reasonable socket timeout options
1 parent ff8aa94 commit 3809d64

File tree

4 files changed

+13
-6
lines changed

4 files changed

+13
-6
lines changed

src/Modbus_TCP_Slave.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "Modbus_TCP_Slave.hpp"
77

8+
#include <algorithm>
89
#include <netinet/in.h>
910
#include <netinet/tcp.h>
1011
#include <stdexcept>
@@ -48,32 +49,38 @@ Slave::Slave(const std::string &ip, unsigned short port, modbus_mapping_t *mappi
4849
}
4950

5051
// set socket options
52+
// enable socket keepalive (--> fail if connection partner is not reachable)
5153
int keepalive = 1;
5254
int tmp = setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive));
5355
if (tmp != 0) {
5456
throw std::system_error(errno, std::generic_category(), "Failed to set socket option SO_KEEPALIVE");
5557
}
5658

59+
// this block makes this source file linux only :(
5760
if (tcp_timeout) {
61+
// set user timeout (~= timeout for tcp connection)
5862
unsigned user_timeout = static_cast<unsigned>(tcp_timeout) * 1000;
5963
tmp = setsockopt(socket, IPPROTO_TCP, TCP_USER_TIMEOUT, &user_timeout, sizeof(keepalive));
6064
if (tmp != 0) {
6165
throw std::system_error(errno, std::generic_category(), "Failed to set socket option TCP_USER_TIMEOUT");
6266
}
6367

68+
// start sending keepalive request after one second without request
6469
unsigned keepidle = 1;
6570
tmp = setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
6671
if (tmp != 0) {
6772
throw std::system_error(errno, std::generic_category(), "Failed to set socket option TCP_KEEPIDLE");
6873
}
6974

70-
unsigned keepintvl = 1;
75+
// send up to 5 keepalive requests during the timeout time, but not more than one per second
76+
unsigned keepintvl = std::max(static_cast<unsigned>(tcp_timeout / 5), 1u);
7177
tmp = setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl));
7278
if (tmp != 0) {
7379
throw std::system_error(errno, std::generic_category(), "Failed to set socket option TCP_KEEPINTVL");
7480
}
7581

76-
unsigned keepcnt = static_cast<unsigned>(tcp_timeout);
82+
// 5 keepalive requests if the timeout time is >= 5s; else send one request each second
83+
unsigned keepcnt = std::min(static_cast<unsigned>(tcp_timeout), 5u);
7784
tmp = setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));
7885
if (tmp != 0) {
7986
throw std::system_error(errno, std::generic_category(), "Failed to set socket option TCP_KEEPCNT");

src/Modbus_TCP_Slave.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace TCP {
1414
//! Modbus TCP slave
1515
class Slave {
1616
private:
17-
modbus_t * modbus; //!< modbus object (see libmodbus library)
17+
modbus_t *modbus; //!< modbus object (see libmodbus library)
1818
modbus_mapping_t *mapping; //!< modbus data object (see libmodbus library)
1919
bool delete_mapping; //!< indicates whether the mapping object was created by this instance
2020
int socket = -1; //!< socket of the modbus connection
@@ -28,7 +28,7 @@ class Slave {
2828
*/
2929
explicit Slave(const std::string &ip = "0.0.0.0",
3030
short unsigned int port = 502,
31-
modbus_mapping_t * mapping = nullptr,
31+
modbus_mapping_t *mapping = nullptr,
3232
std::size_t tcp_timeout = 5);
3333

3434
/*! \brief destroy the modbus slave

src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ int main(int argc, char **argv) {
100100
"Fractional values are possible.",
101101
cxxopts::value<double>())
102102
("t,tcp-timeout",
103-
"tcp timeout in seconds",
103+
"tcp timeout in seconds. Set to 0 to use the system defaults (not recommended).",
104104
cxxopts::value<std::size_t>()->default_value("5"))
105105
("h,help",
106106
"print usage")

src/modbus_shm.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Shm_Mapping {
2626
std::string name = std::string(); //!< name of the object
2727
int fd = -1; //!< file descriptor
2828
std::size_t size; //!< size in bytes
29-
void * addr = nullptr; //!< mapped address
29+
void *addr = nullptr; //!< mapped address
3030
};
3131

3232
//! modbus lib storage object

0 commit comments

Comments
 (0)