46

I am working on a project involving a microcontroller communicating to a PC via Modbus over TCP. My platform is an STM32F4 chip, programming in C with no RTOS. I looked around and found LwIP and Freemodbus and have had pretty good success getting them both to work. Unfortunately, I'm now running into some issues which I'm not sure how to handle.

I've noticed that if I establish connection, then lose connection (by unplugging the Ethernet cable) I will not be able to reconnect (once I've plugged back in, of course). Freemodbus only allows one client and still has the first client registered. Any new clients trying to connect are ignored. It won't drop the first client until after a specific timeout period which, as far as I can tell, is a TCP/IP standard.

My thoughts are...

  1. I need a Modbus module that will handle multiple clients. The new client request after communication loss will be accepted and the first client will eventually be dropped due to the timeout.

    • How do I modify Freemodbus to handle this? Are there examples out there? I've looked into doing it myself and it appears to be a decently sized project.
    • Are there any good Modbus packages out there that handle multiple clients, are not too expensive, and easy to use? I've seen several threads about various options, but I'm not sure any of them meet exactly what I need. I've had a hard time finding any on my own. Most don't support TCP and the ones that do only support one client. Is it generally a bad idea to support multiple clients?
  2. Is something wrong with how I connect to the microcontroller from my PC?

    • Why is the PC changing ports every time it tries to reconnect? If it kept the same port it used before, this wouldn't be a problem
  3. Should I drop the client from Freemodbus as soon as I stop communicating?

    • This seems to go against standards but might work.

I'm leaning towards 1. Especially since I'm going to need to support multiple connections eventually anyways. Any help would be appreciated.

Thanks.

JNMarch
  • 469
  • 4
  • 5
  • 8
    Who ever close voted this is mistaken - this is a highly specific issue (though by no means an uncommon one), which the poster has already put a lot of thought into. – Chris Stratton Oct 04 '13 at 15:19
  • Generally TCP is designed with the idea of "real computers" (of decent resources) talking to each over a link which may be unreliable but recover, and goes to a fair degree of trouble to prevent a new connection from being mistaken for an old one. Thus the PC using a new port number on its end, and neither side immediately forgetting about the other. On a highly resource constrained system on a tightly secured network, one simple thing you can do is make it so that any incoming connection request causes the device to immediately forget any old/existing connection but that's not without risk. – Chris Stratton Oct 04 '13 at 15:22
  • Thanks for the response. I actually just implemented what you mentioned. New requests from the same IP address are accepted, old/existing connection is forgotten. Definitely agree that it comes with it's own risks. Also, it will be a problem when I eventually get around to allowing multiple clients. For now, it should help me move forward. I'm still hoping someone might have a better solution though. – JNMarch Oct 04 '13 at 18:49
  • You have few good options here. 1) find a way to use one of the non-standard ModBus/UDP implementations, 2) treat each message as a connection (have your client close connection once the reply is sent). If doing option 2 maybe look at [TCP for Transactions](http://www.embedded.com/design/connectivity/4023984/TCP-IP-for-Transactions) to minimize the TCP overhead. – Speed8ump Dec 21 '14 at 18:33
  • Do you really need ModBus at all? ModBus is designed for "master/slave" configurations. Originally designed for serial communication over IEEE-422/485 and other multi-drop serial transports. It's cool that tunneling over TCP is possible, but why use such an archaic protocol on something as shiny as the internet? – jwdonahue Dec 28 '17 at 03:48
  • 2
    @jwdonahue Modbus isn't more archaic than TCP is, actually it's still in use, and i'm using it right now. Moreover Modbus provides some things that TCP doesn't e.g. the adresses that you can map to specific functions of a device with a single IP address. To me Modbus TCP is fine. – Dali Jul 05 '19 at 14:38
  • Looks like someone tried to add multi client support over [here](https://github.com/eziya/STM32_HAL_FREEMODBUS_TCP) – Bosz Jul 19 '19 at 14:10
  • Do you actually need to keep the TCP connection alive, or could you manually close the connection by e.g. sending a FIN packet? This obviously results in some overhead as each read/write operation has to be initiated by first opening the connection, but depending on your use case it might be fine. – lindblandro Oct 12 '19 at 11:15
  • I think you need to write a `xMBPortEventGet ` callback that uses an even queue (using `poll` or `select` to fill the queue. I'm not sure. Also - are you limited to the Freemodbus library, of would you consider writing a custom protocol handler? If you don't mind rolling your own (or extracting the protocol handling logic from Freemodbus), you could use `poll` to manage multi-client connectivity manually. There are a bunch of evened IO libraries that will make it easy, such as libuv and facil.io. – Myst Feb 17 '20 at 23:03
  • If you avoid going blocked on the socket, you can time out the old connection, using something like poll() or O_NONBLOCK, and close it. Having a second connection raises the specter of having to lock resources (thus still locked out) or scrambling state (two cooks in the same kitchen). Timeout disconnect needs to restore any half modified state, of course! – David G. Pickett Jul 02 '20 at 19:52
  • My Modbus/TCP implementation drops the connection after each request, to avoid running out of resources. But even if I didn't do so, LWIP has no problem running multiple connections -- that just configuration. – david Dec 07 '21 at 04:23

1 Answers1

1

If you have a limit on the number of modbus clients then dropping old connections when a new one arrives is actually suggested in the modbus implementation guide (https://www.modbus.org/docs/Modbus_Messaging_Implementation_Guide_V1_0b.pdf)

Nevertheless a mechanism must be implemented in case of exceeding the number of authorized connection. In such a case we recommend to close the oldest unused connection.

It has its own problems but everything is a compromise.

Regarding supporting multiple clients...if you think about modbus/rs server - it could only ever have one master at a time. Then replace the serial cable with TCP and you see why it's not uncommon to only support one client (and of course it's easier to program). It is annoying though.

Depending on what you are doing you wont need the whole modbus protocol and implementing the parts you do need is pretty easy. Of course if you have to support absolutely everything its a different prospect. I haven't used freemodbus, or any other library appropriate to your setup, so I can't help with suggestions there.

Regarding the PC using different TCP source port each time - that is how TCP is supposed to work and no fault on your side. If it did reuse the same source port then it wouldn't help you because e.g. sequence numbers would be wrong.

Regarding dropping clients. You are allowed to drop clients though its better not to. Some clients will send a modbus command, notice the connection has failed, reconnect, but not reissue the command. That may be their problem but still nicer to not see it that often where possible. Of course things like battery life might make the calculation different.

user133831
  • 590
  • 5
  • 13