CODESYS - the IEC 61131-3 automation software

Welcome to the official CODESYS Forum by 3S-Smart Software Solutions GmbH | A member of the CODESYS Group
Deutsche Version English version russian version 
It is currently Thu Aug 22, 2019 5:13 pm

All times are UTC+01:00




Post new topic  Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Mon Feb 26, 2018 8:22 am 
Offline
Frequent User
Frequent User

Joined: Fri Feb 23, 2018 3:41 pm
Posts: 149
Hello forum users,

I had a TCP communication to do with some external Equipment, and it is working well, using the exemple provided in codesys help.
To make it easy, i'm using chained TCP_Server, TCP_Connection and TCP_Read (not TCP_ReadBuffer) as descripted in help.

But (yes there is a but) I face a strange behaviour when clients disconnects. TCP_Read block is outputing error before TCP_Connection detects normal/abnormal connection ending.
Is that normal behaviour ?

Regards,
dFx


Top
   
PostPosted: Tue Feb 27, 2018 12:57 pm 
Offline

Joined: Wed Feb 08, 2017 3:43 pm
Posts: 15
dFx wrote:
Hello forum users,

I had a TCP communication to do with some external Equipment, and it is working well, using the exemple provided in codesys help.
To make it easy, i'm using chained TCP_Server, TCP_Connection and TCP_Read (not TCP_ReadBuffer) as descripted in help.

But (yes there is a but) I face a strange behaviour when clients disconnects. TCP_Read block is outputing error before TCP_Connection detects normal/abnormal connection ending.
Is that normal behaviour ?

Regards,
dFx


Hello,

try it to configurate the xEnable parameter of the TCP_Read Functionblock.

Example:
xEnable := sTcpClient.xActive AND NOT sSendMsg.Q AND NOT sTcpWrite.xBusy,

Best regards :D


Top
   
PostPosted: Tue Feb 27, 2018 1:59 pm 
Offline
Frequent User
Frequent User

Joined: Fri Feb 23, 2018 3:41 pm
Posts: 149
Thanks for your reply @Basta87

I don't see any reference about sequencing Read/Write in the NBS manual.

Anyway, I will try it on site and report the result as soon as possible.

This is my call order for NBS function blocks:
Code:
TCP_Server([...]);
TCP_Connection([...]);
TCP_Read(xEnable := TCP_Connection.xActive,[...]);


Top
   
PostPosted: Tue Feb 27, 2018 7:53 pm 
Offline

Joined: Wed Feb 08, 2017 3:43 pm
Posts: 15
Can you post the complete call of the function blocks?


Top
   
PostPosted: Thu Mar 01, 2018 9:18 am 
Offline
Frequent User
Frequent User

Joined: Fri Feb 23, 2018 3:41 pm
Posts: 149
Hope this will help :
Code:
//----------------------------------------------------------------------------------------
// Server Call
//----------------------------------------------------------------------------------------
TCP.fbTCP_Server_V2(
   Enable            := TRUE,
   IPAddr            := TCP.IPAddress,
   Port            := TCP.uiPort,
   SendDataOrder      := ,
   SendDataBuffer      := TCP.abySendBuffer,
   SendDataSize      := TCP.udiSendSize,
   IsActive         => ,
   IsConnected         => ,
   InError            => ,
   ReceivedDataTrigger   => ,
   ReceivedDataBuffer   => ,
   ReceivedDataSize   => ,
   SendDataDone      => ,
   BlockState         => ,
   LastErrorBlock      => ,
   LastError         => );


Code:
// TCP server v2 code
// Manages TCP server with 1 connection with R/W capabilities
FUNCTION_BLOCK TCPServer_FB
VAR_INPUT
   Enable : BOOL := FALSE; // Enable TCP server
   IPAddr : NBS.IP_ADDR := STRUCT(sADDR := '0.0.0.0'); // IP-Address of the TCP server
   Port : UINT := 0; // port OF the TCP server 
   SendDataOrder : BOOL := FALSE; // Data send order (delayed till connection active) 
   SendDataBuffer : ARRAY [1.._udiMaxComBuffer] OF BYTE; // Byte buffer containing data to be sent 
   SendDataSize : UDINT := 0; // Size of data to be sent 
END_VAR
VAR_OUTPUT
   IsActive : BOOL := FALSE; // TCP Server block running 
   IsConnected : BOOL := FALSE; // TCP Client connected 
   InError : BOOL := FALSE; // Indicates that an error has occurred during operation 
   ReceivedDataTrigger : BOOL := FALSE; // Raising edge indicating data received
   ReceivedDataBuffer : ARRAY [1.._udiMaxComBuffer] OF BYTE; // received data buffer 
   ReceivedDataSize : UDINT := 0; // Receive size 
   SendDataDone : BOOL := FALSE; // Data was send correctly
   BlockState : TCPServerStatus_ENUM; // Litteral block status
   LastErrorBlock : TCPServerErrorBlock_ENUM; // Name of block raising last occured error
   LastError : NBS.ERROR; // Last occured error   
END_VAR
VAR
   TCP_Server : NBS.TCP_Server; // TCP_Server block
   TCP_Connection : NBS.TCP_Connection; // TCP_Connection block (1 client can connect)
   TCP_Read : NBS.TCP_Read; // TCP_Read block (reads on first connection)
   TCP_Write : NBS.TCP_Write; // TCP_Write block (writes on first connection)
   _Enable : BOOL; // Internal Enable to handle restart on errors
   RWError : BOOL; // Error occured during Read or Write
   ErrorCounter : CAA.COUNT; // Internal error counter for debbug purposes
END_VAR
VAR CONSTANT
   _udiMaxComBuffer : UDINT := 1500;
END_VAR

// Auto recovery from RW error
IF Enable AND NOT _Enable THEN
   _Enable := TRUE;
ELSE
   IF NOT Enable THEN
      _Enable := FALSE;
      ErrorCounter := 0;
      LastErrorBlock := TCPServerErrorBlock_ENUM.NONE;
      LastError := NBS.ERROR.NO_ERROR;
   END_IF
END_IF

// read/Write error on previous scan
RWError := (
            TCP_Read.xError AND
            (TCP_Read.eError = NBS.ERROR.TCP_RECEIVE_ERROR)
         ) OR
         (
            TCP_Write.xError AND
            (
               (TCP_Read.eError = NBS.ERROR.TCP_SEND_ERROR) OR
               (TCP_Read.eError = NBS.ERROR.TIME_OUT)
            )
         );

// RW Error management
IF RWError AND Enable THEN
   // Something was wrong with read/write
   // Reset full block
   _Enable := FALSE;
END_IF

// TCP Server
// This block handle the socket open/close
TCP_Server(
   xEnable:= _Enable,
   ipAddr:= IPAddr,
   uiPort:= Port,
   xDone=> ,
   xBusy=> ,
   xError=> , 
   eError=> ,
   hServer=>
);

// TCP Connection
// This block handle client connection
// If connection is properly closed, xDone is set
// Then restart connection block to wait for another client
// RW Errors may need connection to be restart (client disconnected improperly is not detected from TCP_Connection block
TCP_Connection(
   xEnable:= TCP_Server.xBusy AND (NOT TCP_Connection.xDone),
   xDone=> ,
   xBusy=> ,
   xError=> ,
   hServer:= TCP_Server.hServer,
   eError=> ,
   xActive=> ,
   hConnection=>
);

// TCP Read
// This block allows to listen for data on opened socket
TCP_Read(
   xEnable:= TCP_Connection.xActive,
   xDone=> ,
   xBusy=> ,
   xError=> ,
   hConnection:= TCP_Connection.hConnection,
   szSize:= _udiMaxComBuffer,
   pData:= ADR(ReceivedDataBuffer),
   eError=> ,
   xReady=> ReceivedDataTrigger,
   szCount=> ReceivedDataSize
);

// TCP Write
// This block allows to send data on opened socket
TCP_Write(
   xExecute:= SendDataOrder,
   udiTimeOut:= 500000, // ┬Ás -> 500ms
   hConnection:= TCP_Connection.hConnection,
   szSize:= SendDataSize,
   pData:= ADR(SendDataBuffer),
   xDone=> SendDataDone,
   xBusy=> ,
   xError=> ,
   eError=>
);

// Generic error management
// Save last error
IF TCP_Server.xError THEN
   ErrorCounter := ErrorCounter + 1;
   LastError := TCP_Server.eError;
   LastErrorBlock := TCPServerErrorBlock_ENUM.SERVER;
ELSE
   IF TCP_Connection.xError THEN
      ErrorCounter := ErrorCounter + 1;
      LastError := TCP_Connection.eError;
      LastErrorBlock := TCPServerErrorBlock_ENUM.CONNECTION;
   ELSE
      IF TCP_Read.xError THEN
         ErrorCounter := ErrorCounter + 1;
         LastError := TCP_Read.eError;
         LastErrorBlock := TCPServerErrorBlock_ENUM.READ;
      ELSE
         IF TCP_Write.xError THEN
            ErrorCounter := ErrorCounter + 1;
            LastError := TCP_Write.eError;
            LastErrorBlock := TCPServerErrorBlock_ENUM.WRITE;
         END_IF
      END_IF
   END_IF
END_IF

// outputs
IsConnected := TCP_Connection.xActive;
IsActive := TCP_Server.xBusy;
InError := TCP_Server.xError;

// Block status
IF NOT _Enable THEN
   BlockState := TCPServerStatus_ENUM.DISABLED;
ELSE
   IF _Enable AND NOT IsActive THEN
      BlockState := TCPServerStatus_ENUM.SERVER_INIT;
   ELSE
      IF IsActive AND NOT IsConnected THEN
         BlockState := TCPServerStatus_ENUM.WAIT_CONNECTION;
      ELSE
         IF IsConnected AND ReceivedDataTrigger  THEN
            BlockState := TCPServerStatus_ENUM.DATA_RECEIVED;
         ELSE
            IF IsConnected AND NOT SendDataOrder THEN
               BlockState := TCPServerStatus_ENUM.CLIENT_CONNECTED;
            ELSE
               IF IsConnected AND SendDataOrder THEN
                  BlockState := TCPServerStatus_ENUM.DATA_WRITTEN;
               END_IF
            END_IF
         END_IF
      END_IF
   END_IF
END_IF



EDIT : I also face another linked problem when using a switch : When my PC is connected as TCP client via a switch, and I disconnect my cable from the switch, there is no TCP error outputed. Even writing ends ok ...
Writing isn't the usual method to detect a down link on a tcp connection ?

To face this, I ping my Partner which is not very reliable (need to know Partner IP address). I do it outside the block, and then I reset Enable flag.


Top
   
PostPosted: Thu Mar 08, 2018 11:13 am 
Offline

Joined: Thu May 12, 2016 7:35 am
Posts: 1
dFx wrote:
Hello forum users,

I had a TCP communication to do with some external Equipment, and it is working well, using the exemple provided in codesys help.
To make it easy, i'm using chained TCP_Server, TCP_Connection and TCP_Read (not TCP_ReadBuffer) as descripted in help.

But (yes there is a but) I face a strange behaviour when clients disconnects. TCP_Read block is outputing error before TCP_Connection detects normal/abnormal connection ending.
Is that normal behaviour ?

Regards,
dFx


Hi all, and thanks for existing.
I'm apparently facing the same problem. I need to implement a server accepting a single client.
To simplify things at the beginning, I implemented a simple echo server, which TCP_Writes the same
buffer contents, as soon as some contents arrives thru TCP_Read. And everything looks ok:
once the connection is established, echo is working.
Things get complcated when I "close" the connection, either from the client or server side: before reconnect,
the connection handle is properly at zero; after reconnect, the connection handle provided by the
TCP_Connection function block appears to be the same as before disconnect; and this is may not
be a problem, but the TCP_Read executed on that handle gives a permanent TCP_RECEIVE_ERROR (6012).
I have no other options than disable/enable the TCP_Server fb, but nothing changes. By the way, even if
this worked, I suppose that it would be not applicable if one had to implement a multiple client solution.
The only operation that really reset things is a controller warm reset.

Just to put some other meat on the grill... I have been using a proprietary TCP server implementation
from ELAU (now Schneider Electric), and it gave me the option to filter incoming connection based on the IP address.
How could this be done with CAA netbase? Or, more simply spelled: how can I obtain the IP address of an incoming connection?

I will really appreciate any comments!


Top
   
PostPosted: Mon Mar 12, 2018 12:20 pm 
Offline

Joined: Wed Mar 07, 2018 12:14 pm
Posts: 4
hi Everyone !

I'm implementing a TCP read write but is quit hard to get it operational. I'm working with Somachine (Codesys environment for Schneider Electric PLC's), In the example from the CAA Net base services is a 'Createmessage fb. I'm not retrieving this in the libs that i have installed. Can someone tell me where to find it?

gr Tom


You do not have the required permissions to view the files attached to this post.


Top
   
PostPosted: Fri Sep 28, 2018 10:58 am 
Offline
Frequent User
Frequent User

Joined: Fri Feb 23, 2018 3:41 pm
Posts: 149
Create message is an exemple of user function that transfert the data into your buffer.


Top
   
PostPosted: Mon Dec 10, 2018 5:27 pm 
Offline

Joined: Mon Aug 13, 2018 1:16 pm
Posts: 2
luciano.assirelli wrote:
Things get complcated when I "close" the connection, either from the client or server side: before reconnect,
the connection handle is properly at zero; after reconnect, the connection handle provided by the
TCP_Connection function block appears to be the same as before disconnect; and this is may not
be a problem, but the TCP_Read executed on that handle gives a permanent TCP_RECEIVE_ERROR (6012).
I have no other options than disable/enable the TCP_Server fb, but nothing changes. By the way, even if
this worked, I suppose that it would be not applicable if one had to implement a multiple client solution.
The only operation that really reset things is a controller warm reset.

HI,
I have the same problem. Did you find some solution please?


Top
   
PostPosted: Tue Dec 11, 2018 10:54 am 
Offline
Frequent User
Frequent User

Joined: Fri Feb 23, 2018 3:41 pm
Posts: 149
dFx wrote:
To face this, I ping my Partner which is not very reliable (need to know Partner IP address). I do it outside the block, and then I reset Enable flag.


Top
   
PostPosted: Thu Jul 18, 2019 9:30 pm 
Offline

Joined: Sun Dec 04, 2016 6:17 pm
Posts: 5
luciano.assirelli wrote:
dFx wrote:
Hello forum users,

I had a TCP communication to do with some external Equipment, and it is working well, using the exemple provided in codesys help.
To make it easy, i'm using chained TCP_Server, TCP_Connection and TCP_Read (not TCP_ReadBuffer) as descripted in help.

But (yes there is a but) I face a strange behaviour when clients disconnects. TCP_Read block is outputing error before TCP_Connection detects normal/abnormal connection ending.
Is that normal behaviour ?

Regards,
dFx


Hi all, and thanks for existing.
I'm apparently facing the same problem. I need to implement a server accepting a single client.
To simplify things at the beginning, I implemented a simple echo server, which TCP_Writes the same
buffer contents, as soon as some contents arrives thru TCP_Read. And everything looks ok:
once the connection is established, echo is working.
Things get complcated when I "close" the connection, either from the client or server side: before reconnect,
the connection handle is properly at zero; after reconnect, the connection handle provided by the
TCP_Connection function block appears to be the same as before disconnect; and this is may not
be a problem, but the TCP_Read executed on that handle gives a permanent TCP_RECEIVE_ERROR (6012).
I have no other options than disable/enable the TCP_Server fb, but nothing changes. By the way, even if
this worked, I suppose that it would be not applicable if one had to implement a multiple client solution.
The only operation that really reset things is a controller warm reset.

Just to put some other meat on the grill... I have been using a proprietary TCP server implementation
from ELAU (now Schneider Electric), and it gave me the option to filter incoming connection based on the IP address.
How could this be done with CAA netbase? Or, more simply spelled: how can I obtain the IP address of an incoming connection?

I will really appreciate any comments!




Not sure if someone is still having issues with this and getting error 6012. This was happening whenever the client was disconnecting from Codesys Server. I had always to do a warm/cold restart. My solution was not to use the Handler FB that comes in the example project. Take all the logic that it is inside the Handler FB, and put it outside. You don't need the Handler FB. It will work.


Top
   
PostPosted: Wed Jul 31, 2019 12:32 pm 
Offline

Joined: Thu Aug 09, 2018 9:57 am
Posts: 1
I also have this problem. I am using code similar to what dFx posted, not like the example with the
Handler FB, and for a single client it works fine resetting the server each time the client disconnects.
Luckily, I only need a server for one client in my current application.

I cannot find anything documenting what causes a TCP_RECEIVE_ERROR (6012).
It surely does not mean that a message was not received correctly, because the messages always come
through correctly.
The error is raised if I physically disconnect the server from the network, but also when the client closes
the connection correctly by setting the TCP FIN flag. I have checked with Wireshark that a full normal
handshake for closing the connection is performed, but still get the error.


Top
   
PostPosted: Fri Aug 09, 2019 9:49 am 
Offline

Joined: Sun Jan 04, 2015 9:36 pm
Posts: 2
matyzs.v wrote:
luciano.assirelli wrote:
Things get complcated when I "close" the connection, either from the client or server side: before reconnect,
the connection handle is properly at zero; after reconnect, the connection handle provided by the
TCP_Connection function block appears to be the same as before disconnect; and this is may not
be a problem, but the TCP_Read executed on that handle gives a permanent TCP_RECEIVE_ERROR (6012).
I have no other options than disable/enable the TCP_Server fb, but nothing changes. By the way, even if
this worked, I suppose that it would be not applicable if one had to implement a multiple client solution.
The only operation that really reset things is a controller warm reset.

HI,
I have the same problem. Did you find some solution please?


I have the same problem as well. Did anyone find some solution please?


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 13 posts ] 

All times are UTC+01:00


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Limited