Is a TCP client/server a good solution for a system which can be controlled by a GUI running on multiple platforms?

  softwareengineering

Consider a software which runs on a dedicated system (basically a Linux box), and controls some machinery. The system has all the required hardware interfaces for the task. The software also has a GUI for controlling said machinery.

However, this system should later be able to be used from external devices, so other software, using the same or similar GUI will be running on various PCs, smartphones, etc. The central SW will contain a TCP server through which the external devices will connect. The central device with its software is to be developed first, and the controlability from external devices will be a later add-on.

My proposal for the “central” software would be to split it into two separate programs. One would be a server without any GUI at all, which will handle all the controlling and hardware interfacing stuff, and a separate software would fulfill solely the roles of the GUI.

Of course, a good MVC separation is possible even within a single program, but the main advantage I see for splitting the program is that the GUI part will be much more easily portable to other systems. Actually, in case of a PC as an external device, the same software can be re-used 100%. For other systems, I guess it would be much easier to port a program 1 to 1, than to port only the GUI part of a more complex program.

The main disadvantage of this solution is that the initial system will be a more complicated, as the GUI needs to communicate via TCP with the controlling part, instead of directly inside the same program.

Are there other major advantages and disadvantages of splitting the application in two separate programs communicating over TCP?

The scope of the project is up to 2 years for a small, 2-3 person team.

5

Yes, this separation of layers is always a good thing, even if its not going to be written for a distributed system. Many systems work by making UI or DB components as isolated as possible to allow for easier maintenance or replacement in the future.

Other system write the main program as a command line app and then write a GUI to drive that. That allows it to be scripted and used in a UI environment too. Its not excessively complicated to do this, you just write your program and then write a UI program later.

For your needs, I’d recommend an embedded HTTP webserver. There are many and they’re very lightweight. You lose nothing by using one instead of a custom TCP server (as you still need to implement security etc) but gain all the standard features of the protocol. You also gain the ability to write your client in the server as a HTML website and control it via a web browser.

2

Your question might be too broad and is quite abstract (not enough implementation details are given: which operating system? which hardware: an Arduino like embedded processor is not the same as an ARM motherboard running some real-time variant of Linux; what machinery ? : a sewing machine is not the same as a nuclear power plant). Also, what kind of users? Are they all internal to a corporation or can they be “general public”?

However, did you consider making your software some specialized web server, using some HTTP server library like libonion or perhaps Wt ? (Of course HTTP is above TCP); then you would still split your software in two parts: one providing HTTP service, the other being some code (e.g. Javascript, AJAX, …) running in browsers.

Then your GUI part would be mostly replaced by browsers (on variety of devices: desktops, smartphones, etc…) speaking HTTP (or HTTPS).

Of course, if you design your application as a specialized web server, you should take very early into account all the implications (notably security, DDOS attacks, …) and you should be aware of web technologies. Of course, things could be different if all users are inside some small corporate intranet (then, you probably care a bit less about DDOS)

But on the client side, most end-user devices (desktops or laptops running Windows, Linux, MacOSX, tablets, smartphones) -those with a display at least- have already sophisticated HTML5 browsers, on which you could leverage.

You might consider other approaches, e.g. remote procedure calls using JSONRPC, using FastCGI to interface to some external existing web server, etc….

If you split your software in several parts, you need to define how they communicate and synchronize, and that is probably operating system and implementation specific (but you’l need some inter-process communication probably provided by some operating system, but you might have some unikernel approach). Without telling more about your software & system & machinery (i.e. physical purpose), you won’t get really meaningful help.

2

A few pitfalls you need to be aware of:

  1. Authentication. Unless you want anyone in the world to operate your machine, you need to make sure only authorized people connect to your hardware controller. A good way to do this might be to use TLS with client- and server certificate. As a bonus this also gives you encryption to protect from eavesdroppers and man-in-the-middle attackers.
  2. The client can not be trusted. You can not assume that the user (authorized or unauthorized) will use your unmodified client software. So make sure your protocol implementation on the server does not allow anything the user interface is not supposed to allow. All client-inputs need to be sanity-checked.
  3. TCP/IP is not very real-time capable. Packets can be suddenly delayed for a whole bunch of reasons. UDP/IP has slightly better real-time capabilities, but has a whole bunch of even nastier surprises, like packets arriving in the wrong order or not at all. When it is important for your use-case that the machine executes commands with exact timing, you can not assume that the commands arrive at the server with the same time-differences between them as they left the client. For example: If you want the machine to run for exactly 5.637 seconds, then sending the on-message and 5.637 seconds later sending the off-message might not work because both messages will need a different time to arrive at the server. You would need to send a “Switch on, wait 5.637 seconds, switch off, now do it” command in one message.

LEAVE A COMMENT