I need to use the TCPClient() program to connect to a TCP server.
It works OK if the server is present & listening. But if the server is not present, the task to which TCPClient() program belongs freezes really badly - in the Task Configuration, for a given period, the run counter for this task increments by 7-8 while the counter for another task with equal priority and cycle time increments by 1000 for the same period. This is if I load the project to PLCWinNT emulator.
If I load the project to a real PLC, the task freezes completely - run counter increments by 1 every 50 - 60 seconds.
As far as I can tell, the problem is in the function call
SysSockConnect(diSocket, ADR(sa), SIZEOF(sa))
which returns after a really huge period of time if there is nothing to connect to.
So my question is, what can I do to avoid this task freezing? SysSockConnect doesn't have a timeout parameter.
Is there a simple way to just check if a device is present, like ping ?
Thanks for any suggestions.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
That's right, by default all the calls of SysLibSockets library are blocking.
I recommend to check the OSCAT networking libray, see http://www.oscat.de, and browse the source for solution.
In the IP_CONROL FB (under the HARDWARE folder), section TC_INIT, you will see the right way to use SysSockConnect.
I think, the relevant part is:
IFplc_841ORplc_881THEN
  SysSockSetOption(socket,6,SOCKET_TCP_NODELAY, ADR(dint_true), SIZEOF(dint_true)); (* Set Push-Bit *)END_IF;SysSockIoctl(socket, SOCKET_FIONBIO, ADR(dint_true)); (* NonBlocking mode *)
And then, once you told ioctl to go to nonblocking mode, "select" might have called after SysSockConnect. (and also before read and write operations) The code used in OSCAT tries to determine if "select" is needed...
    IFc_select=FALSETHEN
      IFSysSockConnect(socket,ADR(sockaddr),SIZEOF(sockaddr))THEN
        c_ready :=TRUE; (* Connected *)
        state:=C_WAIT;
      ELSE
        (*Connectdurchgeführt, abernochnichtverbunden, dannoptionalmitselect-abfrageweitermachen*)
        c_select :=SYSLIBSOCKETS_OPTION.0; (* Bit 0 = TCP-Client - use SysSockselect *)
      END_IF;
    ELSE
      c_Timeout.tv_sec :=0;
      c_Timeout.tv_usec :=0;
      c_fdWrite.fd_count :=1;
      c_fdWrite.fd_array[0] :=socket;
      IFSysSockSelect(SOCKET_FD_SETSIZE,0,ADR(c_fdWrite),0, ADR(c_Timeout))>0THEN
        c_ready :=TRUE; (* Connected *)
        state:=C_WAIT;
      END_IF;
    END_IF;
The other option, is to use SysLibSocketsAsync.lib, but there are some platforms where it's not available. In this case, instead of functions function blocks are called...
(I hope it's not a problem to quote from OSCAT. It's almost like a cookbook for many of us, thanks for the authors. Btw: Does someone know, what are plc_841 and plc_881 bool variables in OSCAT IP_CONTROL? And what is the difference between IP_CONTROL and IP_CONTROL2?
(This could be asked at the OSCAT forum... but once we are here...)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The following code is non-blocking, works fine. It has to be called until xConnected or a timeout reached (a TON for example).
On your platform the SOCKET_TCP_NODELAY might not be called.
xConnected :=FALSE;IFdiSocketID<=0THEN
  saSocketAddress.sin_addr  :=SysSockInetAddr(sIPAddr);
  saSocketAddress.sin_port  :=SysSockHtons(uiPort);
  saSocketAddress.sin_family :=SOCKET_AF_INET;
  diSocketID:=SysSockCreate(diAddressFamily :=SOCKET_AF_INET,
              diType :=SOCKET_STREAM,
              diProtocol       :=0);
  IFdiSocketID=SOCKET_INVALIDTHEN
    RETURN;
  END_IF;
  SysSockSetOption(diSocketID, SOCKET_SOL, SOCKET_SO_SNDBUF, ADR(Settings.diMaxDataSize), SIZEOF(Settings.diMaxDataSize));
  SysSockSetOption(diSocketID, SOCKET_SOL, SOCKET_SO_RCVBUF, ADR(Settings.diMaxDataSize), SIZEOF(Settings.diMaxDataSize));
  SysSockSetOption(diSocketID, SOCKET_SOL, SOCKET_SO_LINGER, ADR(Settings.lOptLinger), SIZEOF(Settings.lOptLinger));
  SysSockSetOption(diSocketID, SOCKET_IPPROTO_TCP, SOCKET_TCP_NODELAY, ADR(Settings.xOptNoDelay),   SIZEOF(Settings.xOptNoDelay));
  SysSockIoctl(diSocketID, SOCKET_FIONBIO, ADR(Settings.diNonBlocking));
  xSelect :=FALSE;END_IFIFNOTxSelectTHEN
  IFSysSockConnect(diSocketID, ADR(saSocketAddress), SIZEOF(saSocketAddress))THEN
    xConnected :=TRUE;
  ELSE
    xSelect :=Settings.xUseSelect;
  END_IFELSE
  fdWrite.fd_count :=1;
  fdWrite.fd_array[0] :=diSocketID;
  IFSysSockSelect(SOCKET_FD_SETSIZE,0,ADR(fdWrite),0, ADR(Settings.tvTimeout))>0THEN
    xConnected :=TRUE;
  END_IF;END_IF
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello, the ftp link seems broke. Can you guys help me with a functional example of socket TCP_IP communication on SysLibSocketsAsync.lib library? Thank you.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Strucc hat geschrieben:
The following code is non-blocking, works fine. It has to be called until xConnected or a timeout reached (a TON for example).
On your platform the SOCKET_TCP_NODELAY might not be called.
xConnected :=FALSE;IFdiSocketID<=0THEN
  saSocketAddress.sin_addr  :=SysSockInetAddr(sIPAddr);
  saSocketAddress.sin_port  :=SysSockHtons(uiPort);
  saSocketAddress.sin_family :=SOCKET_AF_INET;
  diSocketID:=SysSockCreate(diAddressFamily :=SOCKET_AF_INET,
              diType :=SOCKET_STREAM,
              diProtocol       :=0);
  IFdiSocketID=SOCKET_INVALIDTHEN
    RETURN;
  END_IF;
  SysSockSetOption(diSocketID, SOCKET_SOL, SOCKET_SO_SNDBUF, ADR(Settings.diMaxDataSize), SIZEOF(Settings.diMaxDataSize));
  SysSockSetOption(diSocketID, SOCKET_SOL, SOCKET_SO_RCVBUF, ADR(Settings.diMaxDataSize), SIZEOF(Settings.diMaxDataSize));
  SysSockSetOption(diSocketID, SOCKET_SOL, SOCKET_SO_LINGER, ADR(Settings.lOptLinger), SIZEOF(Settings.lOptLinger));
  SysSockSetOption(diSocketID, SOCKET_IPPROTO_TCP, SOCKET_TCP_NODELAY, ADR(Settings.xOptNoDelay),   SIZEOF(Settings.xOptNoDelay));
  SysSockIoctl(diSocketID, SOCKET_FIONBIO, ADR(Settings.diNonBlocking));
  xSelect :=FALSE;END_IFIFNOTxSelectTHEN
  IFSysSockConnect(diSocketID, ADR(saSocketAddress), SIZEOF(saSocketAddress))THEN
    xConnected :=TRUE;
  ELSE
    xSelect :=Settings.xUseSelect;
  END_IFELSE
  fdWrite.fd_count :=1;
  fdWrite.fd_array[0] :=diSocketID;
  IFSysSockSelect(SOCKET_FD_SETSIZE,0,ADR(fdWrite),0, ADR(Settings.tvTimeout))>0THEN
    xConnected :=TRUE;
  END_IF;END_IF
Hi, I'm working on a similar project. I have a raspberry in which I need to run a TCP server where I will receive messages from clients by sockets. I can not get it to work properly, have you managed to get it to work properly? Do you have more information on the server or a example project?
Thank you very much.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
I'm trying the TcpIp.pro example project from here
ftp://ftp2.3s-software.com/pub/Examples ... ion/TcpIp/
I need to use the TCPClient() program to connect to a TCP server.
It works OK if the server is present & listening. But if the server is not present, the task to which TCPClient() program belongs freezes really badly - in the Task Configuration, for a given period, the run counter for this task increments by 7-8 while the counter for another task with equal priority and cycle time increments by 1000 for the same period. This is if I load the project to PLCWinNT emulator.
If I load the project to a real PLC, the task freezes completely - run counter increments by 1 every 50 - 60 seconds.
As far as I can tell, the problem is in the function call
SysSockConnect(diSocket, ADR(sa), SIZEOF(sa))
which returns after a really huge period of time if there is nothing to connect to.
So my question is, what can I do to avoid this task freezing? SysSockConnect doesn't have a timeout parameter.
Is there a simple way to just check if a device is present, like ping ?
Thanks for any suggestions.
That's right, by default all the calls of SysLibSockets library are blocking.
I recommend to check the OSCAT networking libray, see http://www.oscat.de, and browse the source for solution.
In the IP_CONROL FB (under the HARDWARE folder), section TC_INIT, you will see the right way to use SysSockConnect.
I think, the relevant part is:
And then, once you told ioctl to go to nonblocking mode, "select" might have called after SysSockConnect. (and also before read and write operations) The code used in OSCAT tries to determine if "select" is needed...
The other option, is to use SysLibSocketsAsync.lib, but there are some platforms where it's not available. In this case, instead of functions function blocks are called...
(I hope it's not a problem to quote from OSCAT. It's almost like a cookbook for many of us, thanks for the authors. Btw: Does someone know, what are plc_841 and plc_881 bool variables in OSCAT IP_CONTROL? And what is the difference between IP_CONTROL and IP_CONTROL2?
(This could be asked at the OSCAT forum... but once we are here...)
Wago have a PLC called 750-881 and a programmable controler with the number 750-841.
Don't know what it has to do with the code.
thanks for the reply.
I got OSCAT networking library, checked the code and tried some stuff. But this was pure guess-work, and indeed didn't work
Isn't there a simple non-blocking way to only check if there is something at given IP address?
The following code is non-blocking, works fine. It has to be called until xConnected or a timeout reached (a TON for example).
On your platform the SOCKET_TCP_NODELAY might not be called.
Hello, the ftp link seems broke. Can you guys help me with a functional example of socket TCP_IP communication on SysLibSocketsAsync.lib library? Thank you.
Hi, I'm working on a similar project. I have a raspberry in which I need to run a TCP server where I will receive messages from clients by sockets. I can not get it to work properly, have you managed to get it to work properly? Do you have more information on the server or a example project?
Thank you very much.