I have a WCF service hosted inside a Windows service. and I am using NetTcpBinding to connect a WPF client application to this service. I have a callback contract to allow push notifications back to the client, which is working just fine, except when there is more than one client running on the same machine (for example, two client instances running in separate remote desktop sessions). In those circumstances, it appears that only one of the clients is receiving the callback messages. It seems that the problem is caused by the two clients exposing the same callback address, and so the message only goes to one of the listeners.
For example, let's say I have my WCF service hosted on machine 'fakeserver' and 2 WPF clients both running on machine 'fakeclient'. The address that clients use to connect to the WCF service is 'net.tcp://fakeserver:1234/MyService'. Both clients are able to connect to the service just fine. But when the server sends a callback, it's going to send it to 'net.tcp://fakeclient:1234/MyCallback' (since NetTcpBinding is duplex by default, we don't have to specify a separate port for sending callbacks), which has two different clients listening for traffic. Only one of those clients receives the message.
If I were using WSDualHttpBinding, I would be able to specify different ports for the client callback address, thus making the two client callback addresses unique. As it stands, though, I believe both client callback addresses are the same, which is why the message only goes to one client (the last one registered, usually).
How can I ensure that two (or more) WPF clients on the same machine are treated distinctly and each receive any callback messages pushed by the service while still using NetTcpBinding?
It turns out all the callbacks were able to be called from the same machine. The callbacks were being stored uniquely by machine name, so the second time we registered a callback it was replacing the first callback.
Related
I've tried a few different ways to do this, but I keep coming up short.
In short, here's what I need to do:
Create a WCF service that acts as a router between client (desktop pc) run diagnostic tools and "widgets" (that also run desktop windows and are have internet connectivety). Since these "widgets" are typically behind some sort of firewall, we've decided to use an IIS hosted WCF service over a tcp connection (port 800, i believe) for callbacks.
Notifications of what the widget is doing need to be sent, asyncronously up through the router to any "connection" clients.
Clients need to be able to syncronously call into the widgets to get diagnostic data or command them to perform a task.
Right now I have a windows service running on the widget that monitors it's status and provided a link to the internal programs to get data.
I also have a light weight diagnostic application running on desktops.
I have created a single callback interface for both status-push and data-pulls that both the widget monitoring program and desktop program implement.
My first attempt was to have the router service keep a list of registered devices and clients and pass messages between them.
Ie: Desktop calls server.getwidgetcolor("widgetid"); and the service calls _widgetlist["widgetId"].getcolor() and returns it.
Similarly the widget monitoring program calls server.notifywidgetcolorchange("widgetid") and the service calls, on all registered client _widgetlist["widgetid"].clients.Notifiycolorchange()
The problem I am running into is that if a wigdet is calling up to the server at the same time the client is calling down to that widget, both calls timeout.
I initially had the server setup as a singleton, and have played with changing the concurancy mode to multiple or re-entrant, but those didn't seem to work.
Conceptually, i'd like to have the service be per-call and persist somehow, that device and client call backs so that when a call comes in, the server wakes up, depersists the call back, sends the message, then goes back to sleep.
With all that said:
Is that ^^ possible (to persist call-back data so that a per-call server can call back on clients)? If not, could I make the service per session (for clients/widgets) but pass the data between service sessions through some other means? Shared memory? File?
Is the over all design possible/recommended? I've looked into the WCF routing library, but that doesn't seem to do what I want, unless I'm reading it wrong?
Are there other technologies I should be using that can do this more easily?
Thanks,
-Bill
I'm working on a protocol which is designed to be implemented with SOAP over HTTP.
WSDL files are provided by a third party.
I used wsdl.exe to generated a proxy class and created a Web Service Project in VS.
wsdl.exe yourFile.wsdl /l:CS
I got a cs from a unwrapping wsdl.
Snippet:
[System.Web.Services.Protocols.SoapHeaderAttribute("chargeBoxIdentity")]
[System.Web.Services.WebMethodAttribute()]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("/ClearCache", RequestElementName="clearCacheRequest", RequestNamespace="urn://Ocpp/Cp/2012/02/", ResponseElementName="clearCacheResponse", ResponseNamespace="urn://Ocpp/Cp/2012/02/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("status")]
public abstract ClearCacheStatus ClearCache();
Implementation 1 (Server Side)
A central system (Server) connected to devices. When a device initialized, it sends an authorisation to central system.
And Server response an authorisation message back.
I have already done with Server Side which provides all clients send requests to Server. And Server response the messages.It works well.
Implementation 2 (Central system send a message to a device)
The other part of implementation is a central system need to send message to device (ex. clear devices cache, please see a snippet above). I add those methods to web service as well.
My questions are...
How can I send a message to devices through a proxy from Web Service?
It's impossible to call a method from Web Service sending requests to device? Any suggestions?
Or I need to create a project implementing a ClearCache method and format as a SOAP message to trigger?
Thanks!
I dont think it is a good idea to allow the Central system to directly communicate with the clients (Will create a huge noise in the network if the number of devices is high and the server tries to send several messages)..
A better approach will be to allow all the messages that the server intends to send to the client to be cached locally in the server machine. The clients should periodically communicate with the server using another web service and obtain the cached information that you intend to send to the clients.
you can design a method that sends the guid of the client as a parameter in the web service call.
On the server you maintain a database and keep track of the messages that needs to be sent to the clients.
use a timer object in the clients. On elapse of the timer define a method that communicates with the server by sending its guid. On the server side use this guid as a Primary Key to identify wat messages need to be sent to the client and then reply that while returning from the message.
The client then uses this return value to decide how to respond.
I am creating a WCF service where multiple users connect to it. On my WCF I implement callback contracts so that if a user makes a specific action it can notify other computers that are connected to the same WCF service. So if Company A creates an action on the WCF service then the WCF service will make a callback to all Company A machines that are connected to it. Company B will receive no notifications for example.
Anyways so far everything works great NOW. what about in the future where there are more connections at the same time? will that cause a problem?
To avoid that problem will it be better to create a web service where connections are not held open? The problem with this approach is the callback mechanism where the web service needs to send a notification to multiple computers In order to resolve the callback problem I am going to have all machines sending a UDP packet every 10 seconds to the web server. (this will make the router open a port so that the web server can reply in case it needs to) If the web service needs to send a notification to all computers on Company A for instance then it will Send multiple UDP packets. If a computer receives a UDP packet from the web service then it knows it has to make a request to perform the callback. Should I use this approach?
I am currently developing a C# Windows Form Application that I intend to let it interact with a server. The server will receive posting from a mobile application that I have developed and whenever a posting is received, my Windows Form Application should be notified and give me a notification. In order to do this, I intend to use WCF duplex service for it.
E.g. My mobile application sends an posting over to my server. Once my server reads and receives the new posting, the service should send a message over to my winform app to alert me that a posting is received. And the UI of the winform app should update accordingly to what I want to updated. (e.g. adding new panels)
This is basically how I wish for it to work
They way this would work is
WCF Service in running on my server
Windows Form connects to my server's WCF service using Duplex Contract
Mobile app posts to a webpage
Once the webpage receives the posting, the asp.net will invoke the WCF service
WCF duplex service receives the posting and sends the information to the winform app
My winform Application aka WCF Client updates UI with this new message received
My question is, how does step 4 proceed to step 5? To be specific, how does the service sends the information over to the winform app upon receiving the posting.
To be even more specific, once the posting is received from the webpage, the service contract is invoked and the information is sent and received by the service, how does the service make use of the call back channel to send the information over to the winform app and update the UI accordingly?
The answer to this question depends on how your WCF service is hosted and how "big" the service will eventually be (in terms of number of simultaneous clients).
The simplest scenario is a self-hosted WCF service (meaning hosted in a Windows Service or as a desktop application--not in IIS). In this case, you can use InstancePerSession mode and make your service use sessions. In this case, you'll have a 1:1 correspondence between clients and instances of your service class. When a client connects, retrieve the callback reference and store it in a static list outside of the service class. When you need to send a message to one or more clients, simply iterate over (or find the desired client in) your list and call the appropriate function on the callback contract
If you need to host your service in IIS, then the situation is trickier because you have the possibility of multiple processes hosting your service, so your list can potentially get fragmented (or blown away in the event of an app pool recycle). In this case, you'll have to use something external to your service (MSMQ, perhaps) to notify other application pool processes that a message needs to be sent.
In terms of a duplex connection, you are really just able to communicate two way over that one connection, not with all connections of the service without doing some tricky thread stuff and shutting the door on any scalability (or using something outside the service to handle to pub/sub).
One solution though that may work a lot more along the lines of what you want to do would be SignalR. It allows a single client to make a request and then you can broadcast data from that request to other clients (or target it). Take a look at its info, its sole purpose is real time communication in .NET with multiple clients.
Also another note, is that you will want to use some sort of BackgroundWorker or something for your listening thread in WinForms so that the UI is not locked while the background operations are running.
How can I enumerate some sort of location identifier for all of the connected clients for a servicehost? I'm using a duplex connection for long running calculations. The Service host is a singleton.
I can figure out (in .net 3.5) the ip of the calling client but i am unsure how to get the ip of all connected clients.
By default, WCF promotes the use of "per-call" services, e.g. your client calls, the request gets handled, and then the client is disconnected again right away.
WCF doesn't lend itself too well for and isn't intended for long-running connections - so you can't really "enumerate the currently connected users" since there aren't any (or only for a fraction of a second).
WCF is not like a Windows domain server where you log in and stay logged in for an extended period of time.
I don't think there's anything built-in for that, but it'd be pretty easy to build a tracking IServiceBehavior + IDispatchMessageInspector that would inspect the RemoteClientEnpointMessageProperty before the call is dispatched to the service impl and stick the client IP into a shared list, and remove it when the call/session ends.