-1

A C# Restful web service (on a Windows Server 2012 Standard) needs to send commands to equipments via my C# socket server program which is running on the same server. When the web services try to send a command to a selected equipment, the thread of the associated equipment can pick up the command and send it to this equipment. After it is picked, it should be deleted by this thread. At the same time, Thread n which is associated with Equipment n can also pick up a command of Equipment n, and Thread n can delete this command after this command is picked up and sent out. Please refer to the system architecture diagram below.

My question is what is the best way (the most effective, reliable solution) to allow the web services send the command data out and those socket threads can select their associated commands then delete those commands after they are sent out? These commands can be saved into the database and socket threads can check database periodically but this is not effective way especially when the amount of equipment and users is big. Do Named Pipes suit for this scenario and a thread can check these Pipe instances to find an associated command?

System architecture image

Andrew Williamson
  • 8,299
  • 3
  • 34
  • 62
user2018
  • 7
  • 3
  • [Relevant](https://stackoverflow.com/questions/528652/what-is-the-simplest-method-of-inter-process-communication-between-2-c-sharp-pro) – John Wu Oct 17 '18 at 19:24
  • 1
    @JohnWu yes, relevant, but not very specific. I think a quick google for 'Message Broker' might show the pattern you're looking for. I know Azure Service bus can do what you want, with one topic and a subscription within that topic per device. I'm sure the other major message broker services can do the same. – Andrew Williamson Oct 17 '18 at 19:27

3 Answers3

0

The Windows Service can have an additional socket listener (or similar) to receive commands for any of the connected devices, and maintain a BlockingCollection for each device. The thread that owns to connection to each device can simply loop on receiving messages from the BlockingCollectoion and interacting with the device over its socket.

David Browne - Microsoft
  • 80,331
  • 6
  • 39
  • 67
0

I'll expand on my comment here - this is a common scenario, and some of the major software companies (Azure, Amazon, Apache) have implemented solutions. They all have the concept of multiple senders, sending to a single message broker, which then forwards each message directly to the intended recipient. In order for each recipient to receive messages, they have to connect to the message broker, and declare who they are (or what messages they are interested in).

It's important to note that message brokers are common for inter-server communication, but there are more options (usually simpler and more efficient) for inter-process communication on the same machine. So before you pick a solution, you need to consider whether your devices will always communicate with a single socket server, or whether you will scale out to multiple instances at some point.

Some advantages of using a third-party message broker:

  • They can buffer messages for recipients that are not currently connected
  • Most of them provide an easy-to-use C# package, so there is very little setup required
  • They usually provide an SLA of 99.99% uptime or more

Some disadvantages when compared to a purely inter-process solution on the same host:

  • They have higher latency due to their communication with an external message broker server
  • They have a lower maximum throughput, again due to their communication with an external server
  • They usually cost money (sometimes there is an allowance to send e.g. 100,000 messages for free)
Andrew Williamson
  • 8,299
  • 3
  • 34
  • 62
0

Use your database

There are many ways to do this OP, e.g. - Memory mapped files or Anonymous pipes or MSMQ, for 3 examples of the top of my head. But the simplest approach would be to use your database. Specifically I'd do it this way:

  1. Define database tables that are structured in such a manner that they can hold the device list or commands that you want the user to be able to change or send. For example, you might have a table that lists devices for each user, or a table that contains a queue of commands to send to the devices.

  2. Program your web services to update the database. When the user wants to "send" a command, for example, just add it to the table. Don't worry about the hardware yet.

  3. Write a Windows Service (or modify your existing one) to occasionally read the database and "sync up" everything, e.g. send any pending messages to devices. After the sync-up, write a flag back to the database so the web services can read it and tell the user that the command was processed or the update is complete.

This will give you a dirt simple, fault tolerant solution without introducing any new technologies to your architecture.

By storing hardware snapshots, you also provide an extension point for all sorts of fun possibilities, e.g. "undo" functionality, or saved snapshots, or customer support tools that let you see what the end user is trying to set up, or marketing analysis tools that let you see how users are using your product.

But the most important feature is that you could crash/restart all of your services and the solution will just pick up where it left off. So it will be easy to support as well. And hopefully you already know how to work with a database.

John Wu
  • 50,556
  • 8
  • 44
  • 80