1

I am planning a SaaS system, to be written in C#, ASP.NET using WCF that has two separate components:

  1. On a static IP web server in the cloud will be a web app, common to all clients.
  2. Inside each client's office will be another app, installed on a server with IIS.

The site app will obviously be able to connect to the web services published on the web site. But here's the rub - I also want the web app to be able to initiate a connection to the site app... and the on-site server may not necessarily have a static IP. I can't control this, because we may have hundreds of clients at some point in the future, and we cannot limit our saleability by insisting that the customer has a server with fixed IP.

So, how to do this?

I could have the site apps "checking in" with the web every minute or so, to give the web app the possibility of responding with a "while you're here, please do x,y,z..." but that seems very inelegant. Also, if we're talking about hundreds of clients, I don't want to be bombarding my web server with all these "hi there!" messages if they're not actually required.

Is there a better way?

Shaul Behr
  • 36,951
  • 69
  • 249
  • 387

6 Answers6

3

WCF? Here we go:

  • Use a message based approach (exchange message, no stateful method calls).
  • Clients connect to the server. Establish a HTTP-based TWO WAY CONNECTION. This way the server can call back to connected clients. This is standard WCF stuff and works well through NAT with version 4 of the .NET framework.

Voila. In case of a disconnect the client can re-connect, re-identify himself and gets the pending messages.

Lasse Christiansen
  • 10,205
  • 7
  • 50
  • 79
TomTom
  • 61,059
  • 10
  • 88
  • 148
  • +1 - sounds exactly like what I'm looking for! I'm very new to WCF, though - could you please elaborate on how to establish a 2-way connection, or give me a link to the appropriate place in the documentation? – Shaul Behr Dec 16 '10 at 14:30
  • Also, you say it works in .NET v4. I'm using VS2008 (.NET v3.5 SP1). Will it still work? – Shaul Behr Dec 16 '10 at 15:46
  • Not through NAT because in 3.5 the back channel isaa separate connection OPENED FROM THE SERVER. And bypassing firewalls is hard. – TomTom Dec 17 '10 at 09:56
  • OK, so assuming I can get VS2010, am I correct in saying that the binding to use is WSDualHttpBinding? And if I use that, it'll get through the NAT? – Shaul Behr Dec 22 '10 at 15:45
  • THat is the idea. if that does not run through NAT you are in trouble, sort of - well, you could still use dual TCP IP based binding. Nothjing says you need HTTP, and tcp is a lot less performance overhead. – TomTom Dec 22 '10 at 15:55
  • OK, thanks! I'm interested to understand how .NET v4 overcomes the NAT problem... how does the server address the client if it's behind a firewall? – Shaul Behr Dec 22 '10 at 15:58
  • @TomTom, I too am interested as to how WSDualHttpBinding changed in WCF4. Could you please point me to an article or MSDN page about it? – Allon Guralnek Dec 26 '10 at 11:58
1
  1. Dynamic DNS is one possibility, but depends on your clients/customers.
  2. If the site app is created by you, it only has to contact the web server when its address has changed (or when the site server/web app is restarted). Still, a keep-alive heart beat of, say, every 30 min. to 1 hour isn't a bad idea.

Edit: I think SNMP services may provide the answer but I'm not a networking expert. You'll have to do some digging or ask a separate question on stackoverflow.

hythlodayr
  • 2,377
  • 15
  • 23
  • I don't want my customers to have to get their hands dirty with anything other than installing the software; they are most likely not technical people - so dynamic DNS is not really an option. But you're right, a keep-alive heart-beat with the current IP could work. How do you determine your current public IP programmatically, though? – Shaul Behr Dec 16 '10 at 14:38
  • +1 for the point that IP doesn't change that often, and the server can keep a registry of current IPs – Shaul Behr Dec 16 '10 at 14:41
  • Just to be clear on #2, I'm saying you could do both: Occasional heart beat + push from site to web server when it knows things have changed. Just make sure all site servers don't try to contact you at the same time! – hythlodayr Dec 16 '10 at 14:58
  • How do you determine your current public IP programmatically? – Shaul Behr Dec 16 '10 at 15:07
1

IIRC "push communication" is done by letting the client do a HTTP Request with an indefinate timeout. Then the server responds when he has something to say. After the respons the client immediately makes a new request.

It works out the same way like the server is making the connection and takes far less resources than polling.

Vincent Vancalbergh
  • 3,267
  • 2
  • 22
  • 25
  • Interesting idea, but somehow something intuitively feels wrong about having a connection open for potentially a very long time. Are you sure there's no risk in having the request open for so long? Am I inventing problems where none exist? – Shaul Behr Dec 16 '10 at 14:34
  • This is not new. It's how Web 2.0 apps do things (or, with RIA on the rise, I should say "did" ?). Of course the connection remains open, but I don't know for how long (your app and all that). Barring disconnects (upon which your client should attempt to reconnect in a civilized manner) it should be quite painless. – Vincent Vancalbergh Dec 16 '10 at 15:20
  • OK, +1 for the idea, though I'm not sure I'll use it! :) – Shaul Behr Dec 16 '10 at 15:42
  • The technique you describe is called [Comet](http://en.wikipedia.org/wiki/Comet_%28programming%29), and is mainly used in browsers, due to the limitations they impose regarding making connections. In WCF, no such limitations exist, and so this method is not used. Instead, either two HTTP connection are made, one for each direction (called `WSDualHttpBinding`), or by using a single non-HTTP connection, i.e. a plain old socket, that unlike HTTP, allows duplex communication without using tricks like Comet. – Allon Guralnek Dec 26 '10 at 14:10
0

What would you say about Comet technology?

Cromathaar
  • 64
  • 3
0

Sounds like you'll definitely need some sort of registry on the server, then it could attempt to call out to the client apps if it needs work doing.

Generally it is client apps that check in with the server every X seconds - this is how Selenium grid works anyway. With a central hub with which clients register. When the hub receives a request to run some tests it passes the jobs out to the clients to perform.

You may not need the "checking in". The server could just attempt to call out to a registered client app until it finds one that is available.This way only the server would need a static address (could use a DNS name instead of an IP to make it more robust).

Also have a look at XMPP PubSub. This could be a more robust and standardised way to handle this.

Rob Stevenson-Leggett
  • 35,279
  • 21
  • 87
  • 141
0

In the end I decided to go with NetTcpBinding, for reasons best given by @Allon Guralnek here. It's worth clicking through and reading what he has to say...

Community
  • 1
  • 1
Shaul Behr
  • 36,951
  • 69
  • 249
  • 387