views:

289

answers:

7

I want to push data to a client application. The client app can be thick or a thin. The push has to happen over the Internet. How can this be done?

EDIT: Is there a way wherein the client app opens a connection to the server, keeps it alive for its lifetime and then continues receiving data over that connection. Can I build something like this? ANY help's appreciated.

Updates: My thick client will be in Wpf and my thin client will be a silverlight app. I want to have minimal latency. Also for certain categories of data the frequency of updates will be more than 10 per second. I am okay building such a solution if something off the shelf doesn't exist. I just want some pointers/ideas to get started.

A: 

there is a lot of ways - best way - to have the client check the server for updates, and have it pull the data over (using standard ftp protocol - for files or other communication protocols for anything else - like WCF, Web Services ect.) this way you don't need to worry about firewalls and nats.

Viewing you comment - it will be hard, as if the client is behind nat it is not possible without static routing - so if this might be your case, you can't push... you have to open the connection from the client side.

Dani
You're seriously suggesting FTP to get data from the server to the client? How would this handle a "thing" that might get updated as many as 10 times a second? Should he keep re-getting the same file then load/de-serialize the file each time?If he's going to do that then why not just use WCF so objects can be sent instead of files?
Timothy Walters
I wasn't sure if the question refers to small chunk of data (like objects) or something like client updates files ect.ftp is one way - if files are to be pushed, WCF is much preferred for objects. the main answer idea was move to polling and not pushing.
Dani
A: 

The short answer is to use polling.

This question is very similar:

http://stackoverflow.com/questions/471780/asp-net-http-server-push-to-client

Kragen
Is ther a way to avoid polling ?
P.K
kragen: the question is not similar... this question is not talking about a webserver specifically, but about a general 'server'
Toad
A: 

I suggest you use Comet. Check out the following article and example.

lemonad
The question didn't say that a webserver was going to be used. If a webserver is not needed, than comet is a bad idea
Toad
A: 

I needed to do this earlier this year, but I can't find the code on this computer. Does this SO link help?

UPDATE: I found the article that I used when I needed to get this. Warning it uses 3.5 and I think WCF. Code copied from Keyvan Nayyeri's article here:

        OperationContext context = OperationContext.Current;
        MessageProperties messageProperties = context.IncomingMessageProperties;
        RemoteEndpointMessageProperty endpointProperty =
            messageProperties[RemoteEndpointMessageProperty.Name]
            as RemoteEndpointMessageProperty;

        return string.Format("Hello {0}! Your IP address is {1} and your port is {2}",
            value, endpointProperty.Address, endpointProperty.Port);
kenny
+2  A: 

If your client opens a socket to the server, it can be kept open indefinitely. Just make sure every once in a while send a few keepalive packets through. Otherwise 'smart' routers might kill your connection.

So YES, it can be done!

Toad
Yes the client can create sockets. But is it okay to keep a connection open for say 2 days or so?
P.K
This is a question only you or your client can answer. But from technical perspective, leaving a connection open, doesn't affect anything.
Toad
A: 

Your best solution is to use polling like Kragen suggest's, it ensures your server doesn't get bogged down with idle sessions that only exist to send data in rare occasions. Polling gives you the same functionality however you don't have that constant load on your server, that in addition to needing one thread per client (assuming your server spawns a thread for each client like apache, etc). With a thin client (running within a browser) you could do it using AJAX to prevent constant reloading of the page. If within a thick client you could do the same thing but use a background timed event to send requests.

If you still need to push data to your client from the server in a Fat Client scenario the best solution is to have the client open a listening socket, when a request from the server needs to be pushed to the client, the server connects to the client and sends the request (upon authentication the server records that users IP to initiate the connection). In a thin client scenario (via web browser) this is extremely harder to do if not impossible (when proper security policies are used).

We would suggest a more detailed explanation of why you are trying to do this, that would allow us to give you a more 'targeted' solution that fits your needs.

Zyris Development Team
having the client open a listening socket is not a good idea. Usually clients are behind firewalls and the server has no way to contact the server. Better to let the client initiate the connection.
Toad
You are 100% correct, however as you see in the description its mentioned if he HAS to send the data from the server to the client without an active session existing that he would need to have the FatClient app open a port to listen.
Zyris Development Team
A: 

You first need to ask yourself a few questions:

  • Is my 'client' a web browser or an executable?
  • How many clients will be connecting to my server?
  • How often are the clients going to be sent data?
  • How important is it that the clients receive the data immediately (as opposed to a second or two delay)?

If your client is a web browser then your options are more limited, look at Comet for some guidance. As someone else mentioned, here's a good blog post explaining how to do Comet with ASP.NET.

If you are not expecting many clients then opening connections from the client to the server can be a viable solution, take a look at these MSDN pages for information and a basic example: - TcpListener - TcpClient

If you're expecting many clients (more than 50 depending on your server hardware) then your options depend on the answers to the other questions:

If your clients get data frequently and short (seconds) delays are acceptable then polling is an easy solution, you can hide the implementation from the client so it appears that the data is being pushed, but in reality there's a thread in the client that is polling every few seconds.

If your clients don't get data very frequently then something like Comet can be a good option, do a search for "Long Polling WCF" if you're looking for a .NET solution.

Update: Since you've now stated that your client is Silverlight I would strongly recommend these blog posts, talks about something like what you're after:

  • Sending data from the server using sockets (here, here and here)
  • Sending data using WCF Duplex Service (here and here)

The WCF Duplex Service is nicer in that it uses set messages and responses, so there's no need to parse text or binary data yourself. It's basically a version of Comet for Silverlight.

Timothy Walters
Having more than 50 open and waiting connections to a server is really not a problem. Even 5000 wouldn't be a problem.
Toad
@Timothy :thank you for the answer. I have a RIA. I want minimum latency and also the push from the server for certain categories of data will be frequent. I am ready to have a home grown solution if that helps.
P.K
@reinier: it depends :) if we're talking about open connections each with a TcpListener and possibly other data associated with each listener then it could become too taxing on the server very quickly, yes some configurations could handle thousands of connections if the design is good and the hardware can support it.
Timothy Walters
@PK: in that case I would suggest knocking together a quick prototype app using the TcpClient and TcpListener with mock data representative of the amount you expect to see if it suits your needs. If I get time I might post another answer specific to that solution with some sample code.
Timothy Walters