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);  // IP Socket support  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 ...  // Create address  SysSockInetAddr(ip,ADR(address.sin_addr));  address.sin_family:=SOCKET_AF_INET;  address.sin_port:=SysSockHtons(port);  addressPointer:=ADR(address);    // Create socket  iecSocketId:=SysSockCreate(SOCKET_AF_INET,SOCKET_STREAM,0,ADR(iecCreateResult));  IFiecSocketId=RTS_INVALID_HANDLETHEN   // Socket creation failed   ...  ELSE    // Connect socket    iecConnectResult:=SysSockConnect(iecSocketId,addressPointer,SIZEOF(address));    // Send data      xiSentBytes:=SysSockSend(iecSocketId,ADR(sDataSend),SIZEOF(sDataSend),1,ADR(iecSendResult));    IFxiSentBytes=0THEN      // ... failed      ...    ELSE      // Shudown sending data      iecResultShutdown:=SysSockShutdown(iecSocketId,SOCKET_SD_SEND);            // Receive data      // THIS CALL FAILS: iecRecvResult = 529      xiRecvBytes:=SysSockRecv(iecSocketId,ADR(sDataRecv),SIZEOF(sDataRecv),1,ADR(iecRecvResult));      IFxiRecvBytes=0THEN        // ... failed        ...      ELSE        // ... success: process result        ...      END_IF    END_IF  END_IF    // Close socket after sending/getting data   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:='';        //Finalresultvalue  sDataBuff     :STRING(4095);        //Bufferforcomposingresultstring  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;        //JUMPTOSENDDATA      ELSIFnwClient.xErrorTHEN        //Errorshileconnectioncreation        nwClient.xEnable:=FALSE;        xError:=TRUE;        iErrorCode:=1;    //Errorcreatingconnection:reason-1        xBusy:=FALSE;      ELSIFNOTnwClient.xActiveANDNOTnwClient.xErrorANDnwClient.xDoneTHEN        nwClient.xEnable:=FALSE;        xError:=TRUE;            iErrorCode:=2;    //Errorcreatingconnection: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;      //JUMPTOREAD      ELSIFnwTCPWrite.xErrorTHEN        //SenddataERROR        nwTCPWrite.xExecute:=FALSE;        xError:=TRUE;            iErrorCode:=3;    //Datawriteerror        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;    //Noerror        xSuccess:=TRUE;        xBusy:=FALSE;      ELSIFnwTCPRead.eError<>0THEN        xError:=TRUE;        iErrorCode:=4;    //Datareaderror        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)