I have a WPF applications that runs on 2'000 PCs (xp, vista, win 7, win 8),
and the only thing it does is to show new notifications taken from a main server.
At the moment everything works trough pooling and it is hard for the server to handle that load.
I'm now required to provide the same service to another customer which has 4'000 PC,
so pooling is no longer an option.
The customer wants also to be able to specify which Active Directory group should receive the notification,
and every notification must been received by the client even if offline at the time (it will receive it when back online).
Security is not an issue.
I'm searching for the best architecture suited for the task,
this is what I have considered so far:
1) WCF-MSMQ: discarded, it requires msmq active on every client machine.
2) WCF-nettcpbinding publish-subscribe (https://msdn.microsoft.com/en-us/library/ms752254(v=vs.110).aspx):
It would be perfect but how I'm supposed to handle different groups?
Should I check the group of the user and based on that subscribe it to a different topic?
3) Keep all clients always connected to the server:
on connect the client sends it's Domain Name to the server,
the server associate a connection to a user and keep looping trough all the connections while sending notification when available for that user.
I'm not sure how many connections I'm able to always keep opened.
Should I use WCF or just make my own sockets system? The logic is pretty basic but it needs to be available on multiple windows platforms with different .NET version.
Do I still need the clients to send back an ACK when received a notification? Or I can just trust the TCP ACK?
Any suggestions will be much appriciated.
Related
Background
I have multiple servers that I currently connect to remotely to run a number of different commands/scripts to obtain information about the servers and/or applications running on the servers.
I'd like to automate running the commands/scripts (or the code contained in the scripts converted to C#/.NET) and have the server send alerts/notifications/messages to a client (basically a Windows Form) running on multiple workstations, but need some guidance.
For reference, I have limited experience creating Windows Services, but feel fairly confident in being able to create them on the server to handle to command/script automation, which I'm assuming would be the best way to go about handling the command/script automation on the server (since the commands/scripts would need to be run all the time or at set intervals).
Question
How can I connect multiple servers to multiple clients so that the server sends alerts/notifications/messages to the client when a command/script or even an event occurs on the server?
For instance, if an application on the server has a built-in command that can be run to determine the status of the application (up, down, limbo, etc.), I would like the Windows Form on the client to receive an alert from the server when the command returns "down" or "limbo" when it is run, presumably from a Windows Service. The alerts would be displayed on the Windows Form that would be setup basically as a dashboard for the servers that the client can connect to.
An even better outcome would be that the client runs as a background application and a notification appears similar to how Microsoft Outlook displays a notification when new email messages arrive (although these notifications would likely require user interaction to close instead of fading out like the Outlook notifications).
I would also like for the client to use a configuration file that has the connection information for the servers in it so that the servers being used can be changed quickly new servers are added or existing servers are decommissioned.
Research (so far)
I've read about WCF and duplex contracts, and how WCF can be hosted in Windows Services. From what I've read, this seems promising. However, I'm not quite sure how I would set this up so that the client can connect to a WCF service on multiple servers.
One thing that I'm concerned about with WCF is that in all of the WCF examples (which implement a calculator-type service) I've seen the client has to initiate the communication with the server in order to receive a message through a callback. In the calculator service examples, the client sends numbers to the service and the result is provided in the callback. I've also seen an asynchronous example, but in that example the client initiated a single, long running request and the callback returned a single response when it was finished processing.
And, just so I'm clear about bindings in WCF, it is possible to create and use bindings for multiple servers using a configuration file without having to use SvcUtil.exe to generate the code, correct? The reason I ask is because the servers that will be configured will likely be change for different users, so the client needs to be flexible when connecting to the services.
I've just now started looking at Sockets, but I'm not familiar enough with them to know if this would be the better option to achieve my objective.
Summary
I'm just looking for guidance, so if you can help direct me to some resources that will help me achieve my objective, I would appreciate it. I've searched extensively, but the majority of my searching either doesn't apply to my scenario, it is limited to a single server/client interaction, or it is limited to a single server with multiple clients.
Since I'm not sure what direction to go in, I don't have any code examples, although I have implemented the examples in the following Microsoft article: Windows Communication Foundation - Getting Started Tutorial
So you want to build a system of
multiple servers which execute commands on the computer they are running on
multiple clients which will receive the status of the commands executed on server or such information from the server
This would be my advice
Servers can be implemented as windows service. You will be able to administrate them easily this way using the services console or the scm. Checkout this link for a creating a simple C# service How do you write and use a Windows Service in C#?
Also, you can set the service to run as an in-built service user with different levels of permissions in addition to regular user accounts.
I have not used WCF, but usually clients connect to the server; this is a pretty common model, and hence all samples are such. Initiating connection from server is not a big deal (at least in a socket program), but just a bad model. You have to ask yourself, if no client is connected to your servers, how can they relay a status to the end user. You have to think clearly about the communication model. I would suggest a central repository of messages. It can be a file on a shared file system or a database or any such entity which can act as a data repository. This way all servers can convey there messages without caring if a client is connected or not. You can use Sockets to achieve what you want to do. Check the asychronous socket server sample from MSDN to understand how to do it.
Making the client run in the background and just have a notification area icon is also easy in c#. You can use NotifyIcon Class for that. This CodeProject article (Formless System Tray Application) demonstrates its usage. To show notification a la outlook style, you can refer to the following post: How to create form popup from from system tray on windows application (not web) with c#. Look at not only the accepted answer but other answers too; there are lot of useful links in it.
So far we have windows service talking over sockets, storing messages in a central repository and capable of handling multiple clients with toast style pops for client side notification.
You need a far richer client side GUI so the end users can take actions on the messages sent from the server. You can maintain a list of servers in app.config for the client that the client connects on startup. You should to provide a GUI for users to manage all servers and their connections.
Lat but not least, by building such a client server model, you are effectively building a security loophole in your systems. You should implement a good authorization mechanism. Checkout the following post: Authenticate user in WinForms (Nothing to do with ASP.Net)
EDIT:
You can also implement your server to accept "custom command" when you implement it as a service. This way, your client server communication will be standardized by using ServiceController to pass the command. This post might help: How to send a custom command to a .NET windows Service from .NET code?.
Don't get confused in the "command" terminology here. ServiceController issues standard commands to a service for start, stop, pause, resume and restart the service. These are the same items you see on the context menu when you right click a service in the services.msc snap-in. The same way a service can respond to custom commands. In your case the custom command maybe a request to execute a process.
Note that some mechanisms I have described are geared towards an intranet setup while others scale fine on both intranet and internet
I need to create a system comprising of 2 components:
A single server that process and stores data. It also periodically sends out updates to the agents
Multiple agents that are installed at remote endpoints. These collect data in (often, but not always) long-running operations, and this data needs to get to the server
I'm using C# .NET, and ideally I want to use a standards compliant communications method (i.e. one that could theoritically work with Java too, as we may well also use Java agents in the future). Are there any alternatives to web services? What are my options?
The way I see it I have 3 options using web services, and have made the following observations:
Client pull
No open port required at the agent, as it acts like a client
Would need to poll the server for updates
Server push
Open port at the agent, as it acts like a server
Server must poll agents for results
Hybrid
Open port at the agent, as it acts like both a client and a server
No polling; server pushes out updates when required, client sends results when they are available
The 'hybrid' (where agents are both client and server seems the obvious choice - but this application will typically be installed in enterprise and government environments, and I'm concerned they may have an issue with opening a port at the agent. Am I dwelling too much on this?
Are there any other pros and cons I've missed out?
Our friends at http://www.infrastructures.org swear by pull-based mechanisms: http://www.infrastructures.org/papers/bootstrap/bootstrap.html
A major reason why they prefer client-pull over server-push is that clients may be down, and clients must (in general) apply all the operations pushed by servers. If this criteria isn't important in your case, perhaps their conclusion won't be your conclusion, but I do think it is worth reading the "Push vs Pull" section of their paper to determine for yourself.
I would say that in this day and age you can seriously consider only pull technologies. The problem with push is that clients often are hidden behind Network Address Traversal devices (NAT) like wireless routers, broadband modems or company firewalls and they are, more often than not, unreachable from the server.
Making outbound connections ('phone-home'), specially on well known ports like HTTP/HTTPS can basically be assumed as 'possible' even under most constricted networks.
If you use some kind of messaging server (JMS for Java, not sure for C#) then your messaging server is the only server that needs to open a port and you can have two way communication from your agent to the messaging server and from the server to the messaging server. This would allow you to accomplish the hybrid model without needing to open a port on the agent server.
IMHO, I find your best option is the pull option.. that can satisfy your main system requirements as follow:
The first part: Data needs to get to the server, that's obviously can be done through invoking a web method that send that data as a parameter
2nd part:(Server periodically sends out updates to the agents): You can still do that that thru client (regular) pulls by some sort of a web service method that "asks" for the updates since its last pull (some sort of s time stamp to get the updates it missed)
The hybrid method seems a bit weird to me given that I think of an agent as a part of the system that probably might go "offline" quite often, what will the server then do if that failed? it's usually a tough question/decision, specially if you're not sure if this an intended "going offline" or a system/network failure.. etc
I have some of the basic coding down for the program but I do need assistance with something. My goal is to have an alarm go off on multiple PCs in a network indicating that a certain task needs done. Anyone who receives this alarm may stop it, complete the task and log that they did that. What would be the best way to accomplish this in a network? But not every computer in the network will be running this program, just a few.
You could have the application (which runs on some computers in the network) register to participate in a Multicast address. This would allow the machines in the network to exchange data without the need for a central server.
More information:
IP Multicasting: http://en.wikipedia.org/wiki/Multicast
Multicasting in C#: (CodeProject) http://www.codeproject.com/KB/IP/multicast.aspx
Example project: http://www.nmsl.cs.ucsb.edu/MulticastSocketsBook/csharp_send_receive.zip
You would have the program that generates the alarm send out a multicast message
containing all the information required by the other computers to handle the task.
The computers who can execute the job send back a message and the alarm application
then decides which "client" will eventually execute the task by sending that client a "go ahead and do it" message. Only then the "client" application would actually perform the task and report back when it's finished.
Just an idea.
You could also make a web page on the management server where the visiting users can register for alarms. This would mean that you develop and distribute to one computer instead of x number of computers. The alarm would then go off in your web browser, where the users would also respond.
you can have a process listen on the other PCs on a socket, which triggers the alarm.
http://www.devarticles.com/c/a/C-Sharp/Socket-Programming-in-C-sharp-Part-II/1/
In a corporate environment (or possibly some schools), this is a very common IT problem. You'd use their IT deployment/policy enforcement software to distribute the program.
If you're in control of your network environment, then distribute it however seems fit. An intranet web page where you subscribe to alerts makes sense, as Patrick answered.
Doing a push across the network seems unreliable, and would definitely anger IT staff if you ever moved your program into a less friendly network :) Plus, it simply is the wrong model for the job if your network is the internet.
I am writing you because of a new problem I need to solve, and I have now been banging my head against a wall for too long now.
Basically, I need to create an application that can take care of the following:
A user starts an app, which sends a broadcast to the subnet, and recieves a response of all servers there with their IP (and some additional info). The user can then select what server he wants to connect to.
Making it work is simple enough, with identifying the subnet, and broadcasting with UDP, and then having a different server application recieving it and sending back a response . The problem lies with these restrictions, that I need to take into consideration:
There will most likely also be clients on the server machines in the network, meaning that we can assume that the application is present on all machines. Every machine needs to have the listener running, and every machine can launch the GUI for selecting a server.
I am only allowed to add one exception to the firewall - an exception that handles both sending out the broadcasts, recieving broadcasts, sending answers and recieving answers.
I should also only be adding one Windows Service
on a server machine, the listener should run as a windows service, so the user won't notice it. Nor will the user notice, that the response is sent back to the client.
On the client machine, the user can start an application, which will notify the application to emmit the broadcast, and will get all the server responses, so the user can choose one to connect to.
Besides from the application that the user launches in order to select a server, there should be no interaction with the user whatsoever. Not even a popup, requesting the user to allow traffic trough the firewall - it should all be automatically
It needs to work on and in between Win XP, Win Vista and Win 7.
I don't know if I am putting too many constrains on myself, but I really hope that I can make the application with these requirements.
I have a few ideas - I just need to figure out how to do it:
Should i make everything into one application, that I add to the firewall exception list, so it will take care of the traffic on both the server and the client machines?
Should I add a custom exception to the firewall, allowing UDP traffic on a specific port, and then have all traffic flow trough that?
Is there a third and better option for managing that?
It is OK to have the service running on both client and server machines. But can it take care of everything for me - like it handling both the broadcast send/recieve and answer send/recieve? And is there any way to extract the information about servers on the network from a service?
I know it is a lot, but I really hope that you will be able to help me out.
let me know if I wasn't clear enough, or if you need further explanations.
I am coding in C# .Net, and I can utilize all I want from the .Net framework. As soon as I have this functionality implemented
All the best
/Sagi
The kind of peer-to-peer networking problems become simple to the point of being trivial if you designate one machine as the master server. It should have a well-known name that all sub-servers can connect to so they can publish (and withdraw) their availability. A client can then send a query request to the same server and get a list of known servers in return.
This can also solve your firewall problem, the master server could be listening on port 80.
Look into the System.Net.PeerToPeer namespace for a p2p solution supported by the framework.
Maybe a UPnP server and client may be a solution to your problem?
Imagine a WinForms client app that displays fairly complex calculated data fetched from a server app with .Net Remoting over a HTTPChannel.
Since the client app might be running for a whole workday, I need a method to notify the client that new data is available so the user is able to start a reload of the data when he needs to.
Currently I am using remoted .Net events, serializing the event to the client and then rethrowing the event on the side of the client.
I am not very happy with this setup and plan to reimplement it.
Important for me is:
.Net 2.0 based technology
easy of use
low complexity
robust enough to survive a server or client restart still functional
When limited to .Net 2.0, how would you implement such a feature? What technologies / libraries would you use?
I am looking for inspiration on how to attack the problem.
Edit:
The client and server exist in the same organisation, typically a LAN, perhaps a WAN/VPN situation.
This mechanism should only make the client aware that there is new data available. I'd like to keep remoting for getting the actual data to the client since that is working pretty well. MSMQ comes with windows, doesn't it? So it should be ok to use it, but I'm open to any alternative.
I've implemented a similar notification mechanism using MSMQ. The client machine opens a local, public queue, and then advises the server of it's queue name. When changes occur, the server pushes notifications into all the client queues that it's be made aware of. This way the client will know that data is ready, even if it wasn't running when the notification was sent.
The only downside is that it requires MSMQ on the clients, so this may not work if you don't have that kind of control over your client's machines.
For an extra level of redundancy (for example, if a client machine is completely down, and therefore the client queue is unavailable) you could queue notifications on the server prior to dissemination to clients. Notifications in the server queues are only removed when the client is successfully contacted (or perhaps after 3 failed attempts, etc.)
Also in that regard, if the server fails to deliver messages to a client a measured number of times, over a measured period of time, then support entities are notified, error alerts go out, and the client queue is removed from the list of destinations. When I say "measured" I mean a frequency/duration that makes sense to the setting. In my case, it was 5 retries with 5 minute intervals between attempts.
It might also make sense to have the client "renew" it's notification subscription at intervals. If a renewal doesn't occur, then eventually the client queue is removed from the destination list by a "groomer" process in the service.
It sounds as though you need to implement a message-queue based solution. Easy to implement, can survive reboots, and the technology is mature both on the server (MSMQ, MGQSeries) and on the client (System.Messaging)
If you can't find anything built-in and assuming you know the address of all the clients, you could send them a UDP message when data changes. Using UdpClient, this is very easy. The datagram doesn't even need to contain any data if the client app can assume that any UDP data on a certain port means it needs to get new data from the server.
If necessary, you can even make this a broadcast packet (if you don't know who the clients are and they are on the same subnet as the server), so long as the server isn't too "chatty".
Whatever solution you decide on, I would urge you to avoid having the clients poll. This will create a lot of unecessary network traffic and still won't perform all that well.
I would usually use a UI timer on the client to periodically hit the server to see if there was new or updated data. (Assuming you have a mechanism to identify that you have new data like time stamps for new rows, or file time stamps, or a table with last-calculated dates, etc)
That way the server doesn't have to know about the clients. The clients can check at their leisure, etc.