PDA

Просмотр полной версии : SysLibSockets что делать при обрыве связи? )



lazy
07.06.2013, 15:54
Добрый день.
ПЛК110-30. По ТcpIp связываюсь с IcpCon PDS-755 на СOM портах которого висят два датчика измерения влажности Hidronix. Сокеты открываются, обмен идет. Но если связь разорвать, то она не восстанавливается или точнее восстанавливается не всегда. Пробовал после пропадания связи через некоторое время сокеты закрывать и открывать снова - не помогает.
Любопытно, например, сокет открылся и его манипулятор равен единице. Если обмена не было и сокет закрыть и открыть снова манипулятор так же равен единице. Если обмен был то манипулятор равен уже двойке. И обмен не восстанавливается. Такое впечатление что прежний сокет не закрывается хоть SysSockShutdown и SysSockClose возвращают TRUE. Разорвали на время связь - закрыли сокеты и открыли (их манипуляторы изменились) но связь не восстанавливается. Разорвали связь - сбросили ПЛК или выключили питание - связь восстановилась. Как правильно закрыть сокет? )

lazy
07.06.2013, 17:05
Дополню.
Если при пропадании связи закрывать сокет по таймеру и открывать снова. То если конект не восстанавливается ПЛК постепенно откроет все 15 сокетов и на этом все. )
Вот реализация сокета:

CASE o_eCondition OF

STC_EXPECT:
IF m_dnSocket = SOCKET_INVALID AND i_pOptions^.bEnable THEN
m_dnSocket := SysSockCreate( SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_IP );
END_IF
IF m_dnSocket <> SOCKET_INVALID THEN
IF i_pOptions^.bServer THEN
o_eCondition := STC_SETUP;
ELSE
o_eCondition := STC_CONECT;
END_IF
END_IF

STC_SETUP:
m_SAddress.sin_family := SOCKET_AF_INET;
m_SAddress.sin_addr := SOCKET_INADDR_ANY;
m_SAddress.sin_port := SysSockHtons( i_pOptions^.wMyPort );
IF SysSockBind( m_dnSocket, ADR( m_SAddress ), SIZEOF( m_SAddress ) ) THEN
o_eCondition := STC_CONECT;
ELSE
o_eCondition := STC_CLOSED;
END_IF

STC_CONECT:
m_yDelay := m_yDelay + 1;
IF ( m_yDelay MOD 50 ) = 0 THEN
IF i_pOptions^.bServer THEN
IF BOOL_TO_DINT( SysSockListen( m_dnSocket, 1 ) ) = 0 THEN
o_eCondition := STC_WORK;
END_IF
ELSE
m_SAddress.sin_family := SOCKET_AF_INET;
m_SAddress.sin_port := SysSockHtons( i_pOptions^.wOutPort );
m_SAddress.sin_addr := SHL( SHL( SHL(
BYTE_TO_DWORD( i_pOptions^.yOutAddr1 ), 8 )
OR BYTE_TO_DWORD( i_pOptions^.yOutAddr2 ), 8 )
OR BYTE_TO_DWORD( i_pOptions^.yOutAddr3 ), 8 )
OR BYTE_TO_DWORD( i_pOptions^.yOutAddr4 );
IF BOOL_TO_DINT ( SysSockConnect( m_dnSocket, ADR( m_SAddress ), SIZEOF( m_SAddress ) ) ) = 0 THEN
o_eCondition := STC_WORK;
END_IF
END_IF
END_IF

STC_WORK:
IF i_bWrite THEN
o_dnRes := SysSockSend( m_dnSocket, i_pBuffer, i_dwSize, 0 );
ELSE
o_dnRes := SysSockRecv( m_dnSocket, i_pBuffer, i_dwSize, 0 );
END_IF

STC_CLOSED:
IF m_dnSocket <> SOCKET_INVALID THEN
IF SysSockShutdown ( m_dnSocket, 2 )
AND SysSockClose ( m_dnSocket ) THEN
m_dnSocket := SOCKET_INVALID;
END_IF
END_IF
IF m_dnSocket = SOCKET_INVALID THEN
o_eCondition := STC_EXPECT;
END_IF

END_CASE

capzap
07.06.2013, 17:54
можно через системные события гарантированно закрывать сокет, в примерах от S3 это делается при старте плк
Что же касается закрытия во время работы, тут куском кода не обойтись, может в родителе в случае обрыва Вы больше не запускаете этот ФБ и соответственно закрытия не происходит, ну или еще какая нибудь мелочь

lazy
10.06.2013, 09:49
Из CoDeSys я вижу как сокет переходит в состояние STC_CLOSED, а затем STC_EXPECT и его манипулятор становится SOCKET_INVALID.
Закрываются и открываются порты состоянием i_pOptions^.bEnable и переводом родителя в состояние ET_UNKNOWN. За один цикл ПЛК происходит открытие или закрытие одного сокета.

ET_UNKNOWN:
(* open or close sockets *)
FOR m_nI := 0 TO SOCKETS_ DO
m_aSockets[m_nI] ( i_pOptions := ADR( i_pOptions^[m_nI] ) );
IF m_aSockets[m_nI].i_pOptions^.bEnable THEN
IF m_aSockets[m_nI].o_eCondition <> STC_WORK THEN
EXIT;
END_IF
ELSE
IF m_aSockets[m_nI].o_eCondition <> STC_EXPECT THEN
EXIT;
END_IF
END_IF
END_FOR
IF m_nI > SOCKETS_ THEN
o_eCondition := ET_READY;
END_IF