I am writing a client reading data from another device using TCP socket (STREAM type). The Codesys program runs in PLC PiXtend (Raspberry Pi based PLC). The socket is created and connected successfully. The function sending data (SysSockSend) returns success and 81 bytes of sent data. Subsequent call to of SysSockRecv() return RTS_IEC_RESULT = 529 (Socket has been gracefully closed. No more sends/receives allowed.). What is wrong in my code???
VAR
  sDataSend  :STRING;
  sDataRecv  :STRING(4095);
  //IPSocketsupport
  addressPointer   :POINTERTOSOCKADDRESS;
   address      :SOCKADDRESS;
   ip           :STRING(16) :='10.0.0.138';
   port         :WORD :=1367;
  iecCreateResult    :RTS_IEC_RESULT;
  iecConnectResult  :RTS_IEC_RESULT;
  iecSendResult     :RTS_IEC_RESULT;
  iecRecvResult     :RTS_IEC_RESULT;
  iecResultClose    :RTS_IEC_RESULT;
  iecResultShutdown  :RTS_IEC_RESULT;
 Â
   iecSocketId       :RTS_IEC_HANDLE :=0;
  xiSentBytes       :__XINT;
  xiRecvBytes       :__XINT;END_VAR
 ...
  //Createaddress
  SysSockInetAddr(ip, ADR(address.sin_addr));
  address.sin_family :=SOCKET_AF_INET;
  address.sin_port :=SysSockHtons(port);
  addressPointer :=ADR(address);
 Â
  //Createsocket
  iecSocketId :=SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, 0, ADR(iecCreateResult));
  IFiecSocketId=RTS_INVALID_HANDLETHEN
   //Socketcreationfailed
   ...
  ELSE
    //Connectsocket
    iecConnectResult :=SysSockConnect(iecSocketId, addressPointer, SIZEOF(address));
    //Senddata Â
    xiSentBytes :=SysSockSend(iecSocketId, ADR(sDataSend), SIZEOF(sDataSend), 1, ADR(iecSendResult));
    IFxiSentBytes=0THEN
      // ... failed
      ...
    ELSE
      //Shudownsendingdata
      iecResultShutdown :=SysSockShutdown(iecSocketId, SOCKET_SD_SEND);
     Â
      //Receivedata
      //THISCALLFAILS: iecRecvResult=529
      xiRecvBytes :=SysSockRecv(iecSocketId, ADR(sDataRecv), SIZEOF(sDataRecv), 1, ADR(iecRecvResult));
      IFxiRecvBytes=0THEN
        // ... failed
        ...
      ELSE
        // ... success: processresult
        ...
      END_IF
    END_IF
  END_IF
 Â
  //Closesocketaftersending/gettingdata
  iecResultClose :=SysSockClose(iecSocketId);END_IF
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Additional information:
When I try to use simple Python script for same operation, it works well. In Codesys I only created same thing using another programming language.
importsocketfromdatetimeimportdatetimedefnetcat(host,port,content):  s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  s.connect((host,int(port)))  s.sendall(content.encode())  s.shutdown(socket.SHUT_WR)  result=""  whileTrue:    data=s.recv(4096)    ifnotdata:      break    result=result+data.decode()  s.close()  print(result)HOST="10.0.0.138"PORT=1367netcat(HOST,PORT,"{\"id\":1,\"method\":\"sensor-list\",\"params\":[]}")
The Python script reads the result in a loop, my Codesys program reads it in 1 call without the loop. But an expected response is so short, that it must easily fit into a buffer in 1 call. Anyway I tried to read it in a loop too, but the result was 100% same. So the missing loops doesn't seem to be a reason of problem.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
No answer...… Hmmm..... I tried to rewrite using library Network/CAA Net Base Service 3.5.13.0. The code is below. Connection is OK. Sending data seems to send data successfully. Reading data... after some timeout (10s): "TCP_RECEIVE_ERROR" (code 6012).
PROGRAMPOU_TCP_IFACEVAR_INPUT
  xSend    :BOOL :=FALSE;
  sDataSend    :STRING;END_VARVAR
  strIPAddr    : NBS.IP_ADDR;
  uiPort    : UINT;
 Â
  nwClient     : NBS.TCP_Client; Â
  nwTCPWrite   : NBS.TCP_Write;
  nwTCPRead   : NBS.TCP_Read;
 Â
  sDataRecv    :STRING :='';        // Final result value
  sDataBuff     :STRING(4095);        // Buffer for composing result string
  xBusy    :BOOL :=FALSE;
  xSuccess    :BOOL :=FALSE;
  xError    :BOOL :=FALSE;
  iErrorCode    :INT :=0; Â
 Â
  iStep      :INT :=0;END_VAR//Ifthesendcommandisactiveandthesystemisbusy, ignorethesendrequestIFxSendTHEN
  IFxBusyTHEN
     xSend :=FALSE;
  END_IF Â
END_IFIFxSendTHEN
  strIPAddr.sAddr :='10.0.0.138';
  uiPort :=1367;
 Â
  //Initstatusvariables
  xSend :=FALSE;
  xBusy :=TRUE;
  xSuccess :=FALSE;
  xError :=FALSE;
  iErrorCode :=0; Â
  sDataRecv :='';
  iStep :=0;
  nwClient(xEnable :=FALSE);
  nwTCPRead(xEnable :=FALSE);
  nwTCPWrite(xExecute :=FALSE);END_IFIFxBusyTHEN
  CASEiStepOF
    0: //Prepareconnection
      nwClient(xEnable :=TRUE, ipAddr :=strIPAddr, uiPort :=uiPort, udiTimeOut :=10000000); Â
      IFnwClient.xActiveTHEN
        //Successfulyconnected
        iStep :=1;        // JUMP TO SEND DATA
      ELSIFnwClient.xErrorTHEN
        //Errorshileconnectioncreation
        nwClient.xEnable :=FALSE;
        xError :=TRUE;
        iErrorCode :=1;    // Error creating connection: reason - 1
        xBusy :=FALSE;
      ELSIFNOTnwClient.xActiveANDNOTnwClient.xErrorANDnwClient.xDoneTHEN
        nwClient.xEnable :=FALSE;
        xError :=TRUE;   Â
        iErrorCode :=2;    // Error creating connection: reason - 2
        xBusy :=FALSE;
      END_IF
     Â
    1: //Senddata
      IFnwTCPWrite.xBusy=FALSEANDnwTCPWrite.xError=FALSEANDnwTCPWrite.xDone=FALSETHEN
        nwTCPWrite.hConnection :=nwClient.hConnection;
        nwTCPWrite.pData :=ADR(sDataSend);
        nwTCPWrite.szSize :=INT_TO_UDINT(LEN(sDataSend));
        nwTCPWrite.udiTimeOut :=10000000;
       Â
        nwTCPWrite.xExecute :=TRUE;
      END_IF
   Â
      IFnwTCPWrite.xDone=TRUETHEN
        //DataISSENT!
        nwTCPWrite.xExecute :=FALSE;
        iStep :=2;      // JUMP TO READ
      ELSIFnwTCPWrite.xErrorTHEN
        //SenddataERROR
        nwTCPWrite.xExecute :=FALSE;
        xError :=TRUE;   Â
        iErrorCode :=3;    // Data write error
        xBusy :=FALSE;
      ELSE
        nwTCPWrite(); Â
      END_IF Â
   Â
    2: //Readdata
      nwTCPRead(xEnable :=TRUE,
             hConnection :=nwClient.hConnection,
            szSize :=SIZEOF(sDataBuff),
            pData :=ADR(sDataBuff));
           Â
      IFnwTCPRead.xReadyANDnwTCPRead.eError=0THEN
        IFnwTCPRead.szCount>0THEN
          sDataRecv :=sDataBuff;
        ELSE
          sDataRecv :='';
        END_IF
        xError :=FALSE;
        iErrorCode :=0;    // No error
        xSuccess :=TRUE;
        xBusy :=FALSE;
      ELSIFnwTCPRead.eError<>0THEN
        xError :=TRUE;
        iErrorCode :=4;    // Data read error
        xBusy :=FALSE;
      END_IF
  END_CASE;END_IF
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I tried to run the program under SIMULATION mode on my development PC. Simultaneously I ran also Wireshark to capture network communication between simu-PLC and the second device. Unfortunately under simulation mode it doesn't work. No socket is opened The function returns zero socket handle but the result error code is also zero. Incredible! Therefore I cannot capture network traffic between PLC and controlled device. Crazy world!!!!!!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hey zkid, I am sorry your question was not answered and I hope you found the solution.
If you don't mind since you seem to have a good understanding of the TCP sockets. I am working with modbus TCP and it uses the MainTask as its bus cycle task.
This task has a very small code but when checking its max cycle time, sometimes it reaches to 21ms!
So my theory is, do we open and close TCP connection in each modbus cycle transmission? As that would explain reaching 21ms sometimes, right?.
But I dont know how or where to check that.
Is the TCP socket always on or always off? (once the connection is established)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am writing a client reading data from another device using TCP socket (STREAM type). The Codesys program runs in PLC PiXtend (Raspberry Pi based PLC). The socket is created and connected successfully. The function sending data (SysSockSend) returns success and 81 bytes of sent data. Subsequent call to of SysSockRecv() return RTS_IEC_RESULT = 529 (Socket has been gracefully closed. No more sends/receives allowed.). What is wrong in my code???
Additional information:
When I try to use simple Python script for same operation, it works well. In Codesys I only created same thing using another programming language.
The Python script reads the result in a loop, my Codesys program reads it in 1 call without the loop. But an expected response is so short, that it must easily fit into a buffer in 1 call. Anyway I tried to read it in a loop too, but the result was 100% same. So the missing loops doesn't seem to be a reason of problem.
No answer...… Hmmm..... I tried to rewrite using library Network/CAA Net Base Service 3.5.13.0. The code is below. Connection is OK. Sending data seems to send data successfully. Reading data... after some timeout (10s): "TCP_RECEIVE_ERROR" (code 6012).
I tried to run the program under SIMULATION mode on my development PC. Simultaneously I ran also Wireshark to capture network communication between simu-PLC and the second device. Unfortunately under simulation mode it doesn't work. No socket is opened The function returns zero socket handle but the result error code is also zero. Incredible! Therefore I cannot capture network traffic between PLC and controlled device. Crazy world!!!!!!
Hey zkid, I am sorry your question was not answered and I hope you found the solution.
If you don't mind since you seem to have a good understanding of the TCP sockets. I am working with modbus TCP and it uses the MainTask as its bus cycle task.
This task has a very small code but when checking its max cycle time, sometimes it reaches to 21ms!
So my theory is, do we open and close TCP connection in each modbus cycle transmission? As that would explain reaching 21ms sometimes, right?.
But I dont know how or where to check that.
Is the TCP socket always on or always off? (once the connection is established)