Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
U
uniset2
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
UniSet project repositories
uniset2
Commits
12ee9dc5
Commit
12ee9dc5
authored
Nov 20, 2021
by
Pavel Vainerman
Committed by
Pavel Vainerman
Nov 21, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[modbus slave]: supported socket reopen timeout
parent
a8ff6725
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
133 additions
and
7 deletions
+133
-7
MBSlave.cc
extensions/ModbusSlave/MBSlave.cc
+9
-0
MBSlave.h
extensions/ModbusSlave/MBSlave.h
+1
-0
ModbusTCPServer.h
include/modbus/ModbusTCPServer.h
+15
-0
ModbusTCPServer.cc
src/Communications/Modbus/ModbusTCPServer.cc
+108
-7
No files found.
extensions/ModbusSlave/MBSlave.cc
View file @
12ee9dc5
...
...
@@ -248,6 +248,13 @@ namespace uniset
vmonit
(
sessTimeout
);
tmpval
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-socket-timeout"
,
it
.
getProp
(
"socketTimeout"
));
if
(
tmpval
>
0
)
sockTimeout
=
tmpval
;
vmonit
(
sockTimeout
);
tmpval
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-session-maxnum"
,
it
.
getProp
(
"sessMaxNum"
));
if
(
tmpval
>
0
)
...
...
@@ -642,6 +649,8 @@ namespace uniset
i
.
second
.
ptTimeout
.
reset
();
tcpserver
->
setMaxSessions
(
sessMaxNum
);
tcpserver
->
setSessionTimeout
(
sessTimeout
);
tcpserver
->
setSocketTimeout
(
sockTimeout
);
if
(
vaddr
.
empty
()
)
{
...
...
extensions/ModbusSlave/MBSlave.h
View file @
12ee9dc5
...
...
@@ -596,6 +596,7 @@ namespace uniset
// TCPServer section..
void
initTCPClients
(
UniXML
::
iterator
confnode
);
timeout_t
sockTimeout
=
{
UniSetTimer
::
WaitUpTime
};
/*!< таймаут на переоткрытие сокета (если нет сессий) */
timeout_t
sessTimeout
=
{
2000
};
/*!< таймаут на сессию */
timeout_t
updateStatTime
=
{
4000
};
ModbusTCPServer
::
Sessions
sess
;
/*!< список открытых сессий */
...
...
include/modbus/ModbusTCPServer.h
View file @
12ee9dc5
...
...
@@ -92,6 +92,12 @@ namespace uniset
void
setTimer
(
timeout_t
msec
);
timeout_t
getTimer
()
const
noexcept
;
// Таймаут для переоткрытия сокета.
// Если в течение msec миллисекунд нет действующих соединений
// сокет переоткрывается
void
setSocketTimeout
(
timeout_t
msec
);
timeout_t
getSocketTimeout
()
const
noexcept
;
protected
:
// ожидание (при этом время отдаётся eventloop-у)
...
...
@@ -105,6 +111,8 @@ namespace uniset
virtual
void
ioAccept
(
ev
::
io
&
watcher
,
int
revents
);
void
onTimer
(
ev
::
timer
&
t
,
int
revents
);
void
onSocketTimeout
(
ev
::
timer
&
t
,
int
revents
);
void
onSocketResetTimeout
(
ev
::
async
&
watcher
,
int
revents
)
noexcept
;
void
sessionFinished
(
const
ModbusTCPSession
*
s
);
...
...
@@ -145,6 +153,11 @@ namespace uniset
ev
::
timer
ioTimer
;
std
::
shared_ptr
<
UTCPSocket
>
sock
;
ev
::
timer
sockTimeout
;
timeout_t
socketTimeout_msec
=
{
UniSetTimer
::
WaitUpTime
};
double
tmSockTimeout
=
{
0
.
0
};
ev
::
async
asyncResetSockTimeout
;
std
::
unordered_set
<
ModbusRTU
::
ModbusAddr
>
vmbaddr
;
TimerSignal
m_timer_signal
;
...
...
@@ -154,6 +167,8 @@ namespace uniset
PassiveTimer
ptWait
;
private
:
void
createSocket
();
// транслирование сигналов от Sessions..
void
postReceiveEvent
(
ModbusRTU
::
mbErrCode
res
);
ModbusRTU
::
mbErrCode
preReceiveEvent
(
const
std
::
unordered_set
<
ModbusRTU
::
ModbusAddr
>
vaddr
,
timeout_t
tout
);
...
...
src/Communications/Modbus/ModbusTCPServer.cc
View file @
12ee9dc5
...
...
@@ -46,6 +46,8 @@ namespace uniset
io
.
set
<
ModbusTCPServer
,
&
ModbusTCPServer
::
ioAccept
>
(
this
);
ioTimer
.
set
<
ModbusTCPServer
,
&
ModbusTCPServer
::
onTimer
>
(
this
);
sockTimeout
.
set
<
ModbusTCPServer
,
&
ModbusTCPServer
::
onSocketTimeout
>
(
this
);
asyncResetSockTimeout
.
set
<
ModbusTCPServer
,
&
ModbusTCPServer
::
onSocketResetTimeout
>
(
this
);
}
// -------------------------------------------------------------------------
...
...
@@ -108,36 +110,50 @@ namespace uniset
return
evIsActive
()
&&
sock
;
}
// -------------------------------------------------------------------------
void
ModbusTCPServer
::
evprepare
()
void
ModbusTCPServer
::
createSocket
()
{
try
{
sock
=
make_shared
<
UTCPSocket
>
(
iaddr
,
port
);
auto
tmpSock
=
make_shared
<
UTCPSocket
>
(
iaddr
,
port
);
if
(
sock
)
sock
.
reset
();
sock
=
tmpSock
;
}
catch
(
const
Poco
::
Net
::
NetException
&
ex
)
{
ostringstream
err
;
err
<<
"(ModbusTCPServer::
evprepare
): connect "
<<
iaddr
<<
":"
<<
port
<<
" err: "
<<
ex
.
what
();
err
<<
"(ModbusTCPServer::
createSocket
): connect "
<<
iaddr
<<
":"
<<
port
<<
" err: "
<<
ex
.
what
();
dlog
->
crit
()
<<
err
.
str
()
<<
endl
;
throw
uniset
::
SystemError
(
err
.
str
());
}
catch
(
const
std
::
exception
&
ex
)
{
ostringstream
err
;
err
<<
"(ModbusTCPServer::evprepare
): connect "
<<
iaddr
<<
":"
<<
port
<<
" err: "
<<
ex
.
what
();
err
<<
"(ModbusTCPServer::createSocket
): connect "
<<
iaddr
<<
":"
<<
port
<<
" err: "
<<
ex
.
what
();
dlog
->
crit
()
<<
err
.
str
()
<<
endl
;
throw
uniset
::
SystemError
(
err
.
str
());
}
sock
->
setBlocking
(
false
);
}
// -------------------------------------------------------------------------
void
ModbusTCPServer
::
evprepare
()
{
createSocket
();
io
.
set
(
loop
);
io
.
start
(
sock
->
getSocket
(),
ev
::
READ
);
ioTimer
.
set
(
loop
);
asyncResetSockTimeout
.
set
(
loop
);
asyncResetSockTimeout
.
start
();
ioTimer
.
set
(
loop
);
if
(
tmTime_msec
!=
UniSetTimer
::
WaitUpTime
)
ioTimer
.
start
(
0
,
tmTime
);
sockTimeout
.
set
(
loop
);
if
(
socketTimeout_msec
>
0
&&
socketTimeout_msec
!=
UniSetTimer
::
WaitUpTime
)
sockTimeout
.
start
(
0
,
tmSockTimeout
);
}
// -------------------------------------------------------------------------
void
ModbusTCPServer
::
terminate
()
...
...
@@ -155,6 +171,8 @@ namespace uniset
ioTimer
.
stop
();
io
.
stop
();
sockTimeout
.
stop
();
asyncResetSockTimeout
.
stop
();
auto
lst
(
slist
);
...
...
@@ -183,6 +201,7 @@ namespace uniset
{
slist
.
erase
(
i
);
sessCount
--
;
asyncResetSockTimeout
.
send
();
return
;
}
}
...
...
@@ -238,7 +257,29 @@ namespace uniset
// -------------------------------------------------------------------------
timeout_t
ModbusTCPServer
::
getTimer
()
const
noexcept
{
return
tmTime
;
return
tmTime_msec
;
}
// -------------------------------------------------------------------------
void
ModbusTCPServer
::
setSocketTimeout
(
timeout_t
msec
)
{
socketTimeout_msec
=
msec
;
if
(
msec
==
UniSetTimer
::
WaitUpTime
||
msec
==
0
)
{
socketTimeout_msec
=
0
;
if
(
sockTimeout
.
is_active
()
)
sockTimeout
.
stop
();
}
else
{
tmSockTimeout
=
(
double
)
msec
/
1000.
;
if
(
sockTimeout
.
is_active
()
)
sockTimeout
.
start
(
0
,
tmSockTimeout
);
}
}
// ------------------------------------------------------------------------
timeout_t
ModbusTCPServer
::
getSocketTimeout
()
const
noexcept
{
return
socketTimeout_msec
;
}
// -------------------------------------------------------------------------
void
ModbusTCPServer
::
iowait
(
timeout_t
msec
)
...
...
@@ -286,6 +327,9 @@ namespace uniset
connCount
++
;
if
(
sockTimeout
.
is_active
()
)
sockTimeout
.
again
();
auto
s
=
make_shared
<
ModbusTCPSession
>
(
ss
,
vmbaddr
,
sessTimeout
);
s
->
connectReadCoil
(
sigc
::
mem_fun
(
this
,
&
ModbusTCPServer
::
readCoilStatus
)
);
s
->
connectReadInputStatus
(
sigc
::
mem_fun
(
this
,
&
ModbusTCPServer
::
readInputStatus
)
);
...
...
@@ -350,7 +394,64 @@ namespace uniset
}
}
// -------------------------------------------------------------------------
void
ModbusTCPServer
::
onSocketResetTimeout
(
ev
::
async
&
watcher
,
int
revents
)
noexcept
{
if
(
EV_ERROR
&
revents
)
{
if
(
dlog
->
is_crit
()
)
dlog
->
crit
()
<<
myname
<<
"(ModbusTCPServer::onSocketResetTimeout): invalid event"
<<
endl
;
return
;
}
if
(
dlog
->
is_info
()
)
dlog
->
info
()
<<
myname
<<
"(ModbusTCPServer::onSocketResetTimeout): reset socket timeout.."
<<
endl
;
if
(
sockTimeout
.
is_active
()
)
sockTimeout
.
again
();
}
// -------------------------------------------------------------------------
void
ModbusTCPServer
::
onSocketTimeout
(
ev
::
timer
&
t
,
int
revents
)
{
if
(
EV_ERROR
&
revents
)
{
if
(
dlog
->
is_crit
()
)
dlog
->
crit
()
<<
myname
<<
"(ModbusTCPServer::onSocketTimeout): invalid event"
<<
endl
;
return
;
}
{
std
::
lock_guard
<
std
::
mutex
>
l
(
sMutex
);
if
(
!
slist
.
empty
())
{
if
(
dlog
->
is_info
()
)
dlog
->
info
()
<<
myname
<<
"(ModbusTCPServer::onSocketTimeout): check socket [OK].."
<<
endl
;
t
.
again
();
return
;
}
}
if
(
dlog
->
is_warn
()
)
dlog
->
warn
()
<<
myname
<<
"(ModbusTCPServer::onSocketTimeout): no connections.. recreate socket.."
<<
endl
;
try
{
createSocket
();
if
(
io
.
is_active
()
)
io
.
stop
();
io
.
start
(
sock
->
getSocket
(),
ev
::
READ
);
}
catch
(
std
::
exception
&
ex
)
{
if
(
dlog
->
is_crit
()
)
dlog
->
crit
()
<<
myname
<<
"(ModbusTCPServer::onSocketTimeout): recreate socket ERROR: "
<<
ex
.
what
()
<<
endl
;
}
t
.
again
();
}
// -------------------------------------------------------------------------
mbErrCode
ModbusTCPServer
::
realReceive
(
const
std
::
unordered_set
<
ModbusAddr
>&
vaddr
,
timeout_t
msecTimeout
)
{
return
ModbusRTU
::
erOperationFailed
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment