Skip to content

Commit ff8aa94

Browse files
NikolasK-gitNikolasK-source
authored andcommitted
more socket options
1 parent 2d90320 commit ff8aa94

File tree

3 files changed

+37
-11
lines changed

3 files changed

+37
-11
lines changed

src/Modbus_TCP_Slave.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace TCP {
1717

1818
static constexpr int MAX_REGS = 0x10000;
1919

20-
Slave::Slave(const std::string &ip, unsigned short port, modbus_mapping_t *mapping) {
20+
Slave::Slave(const std::string &ip, unsigned short port, modbus_mapping_t *mapping, std::size_t tcp_timeout) {
2121
// create modbus object
2222
modbus = modbus_new_tcp(ip.c_str(), static_cast<int>(port));
2323
if (modbus == nullptr) {
@@ -54,10 +54,30 @@ Slave::Slave(const std::string &ip, unsigned short port, modbus_mapping_t *mappi
5454
throw std::system_error(errno, std::generic_category(), "Failed to set socket option SO_KEEPALIVE");
5555
}
5656

57-
unsigned user_timeout = 5000;
58-
tmp = setsockopt(socket, IPPROTO_TCP, TCP_USER_TIMEOUT, &keepalive, sizeof(user_timeout));
59-
if (tmp != 0) {
60-
throw std::system_error(errno, std::generic_category(), "Failed to set socket option SO_KEEPALIVE");
57+
if (tcp_timeout) {
58+
unsigned user_timeout = static_cast<unsigned>(tcp_timeout) * 1000;
59+
tmp = setsockopt(socket, IPPROTO_TCP, TCP_USER_TIMEOUT, &user_timeout, sizeof(keepalive));
60+
if (tmp != 0) {
61+
throw std::system_error(errno, std::generic_category(), "Failed to set socket option TCP_USER_TIMEOUT");
62+
}
63+
64+
unsigned keepidle = 1;
65+
tmp = setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
66+
if (tmp != 0) {
67+
throw std::system_error(errno, std::generic_category(), "Failed to set socket option TCP_KEEPIDLE");
68+
}
69+
70+
unsigned keepintvl = 1;
71+
tmp = setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl));
72+
if (tmp != 0) {
73+
throw std::system_error(errno, std::generic_category(), "Failed to set socket option TCP_KEEPINTVL");
74+
}
75+
76+
unsigned keepcnt = static_cast<unsigned>(tcp_timeout);
77+
tmp = setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));
78+
if (tmp != 0) {
79+
throw std::system_error(errno, std::generic_category(), "Failed to set socket option TCP_KEEPCNT");
80+
}
6181
}
6282
}
6383

src/Modbus_TCP_Slave.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ class Slave {
2626
* @param port port to listen for incoming connections (default 502)
2727
* @param mapping modbus mapping object (nullptr: an mapping object with maximum size is generated)
2828
*/
29-
explicit Slave(const std::string &ip = "0.0.0.0",
30-
short unsigned int port = 502,
31-
modbus_mapping_t * mapping = nullptr);
29+
explicit Slave(const std::string &ip = "0.0.0.0",
30+
short unsigned int port = 502,
31+
modbus_mapping_t * mapping = nullptr,
32+
std::size_t tcp_timeout = 5);
3233

3334
/*! \brief destroy the modbus slave
3435
*

src/main.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,17 @@ int main(int argc, char **argv) {
9191
"In most cases it is sufficient to set teh response timeout. "
9292
"Fractional values are possible.",
9393
cxxopts::value<double>())
94-
("t,response-timeout",
94+
("response-timeout",
9595
"set the timeout interval in seconds used to wait for a response. "
9696
"When a byte timeout is set, if elapsed time for the first byte of response is longer than "
9797
"the given timeout, the a timeout is detected."
9898
"When byte timeout is disabled, the full confirmation response must be received before "
9999
"expiration of the response timeout."
100100
"Fractional values are possible.",
101101
cxxopts::value<double>())
102+
("t,tcp-timeout",
103+
"tcp timeout in seconds",
104+
cxxopts::value<std::size_t>()->default_value("5"))
102105
("h,help",
103106
"print usage")
104107
("version",
@@ -178,8 +181,10 @@ int main(int argc, char **argv) {
178181
// create slave
179182
std::unique_ptr<Modbus::TCP::Slave> slave;
180183
try {
181-
slave = std::make_unique<Modbus::TCP::Slave>(
182-
args["ip"].as<std::string>(), args["port"].as<uint16_t>(), mapping.get_mapping());
184+
slave = std::make_unique<Modbus::TCP::Slave>(args["ip"].as<std::string>(),
185+
args["port"].as<uint16_t>(),
186+
mapping.get_mapping(),
187+
args["tcp-timeout"].as<std::size_t>());
183188
slave->set_debug(args.count("monitor"));
184189
} catch (const std::runtime_error &e) {
185190
std::cerr << e.what() << std::endl;

0 commit comments

Comments
 (0)