Chapter 13. Networking

Most interesting computer systems are distributed these days—it’s increasingly unusual for a program to run in isolation on a single machine. So .NET provides various ways to communicate across networks. The array of networking options looks a little bewildering at first: there are 10 namespaces whose names start with System.Net containing more than 250 classes, and that’s not even the complete set—there’s an even bigger API for producing and consuming web services.

Fortunately, it’s simpler than this makes it seem—despite the large API surface area most of the options fall into three categories. There’s WCF—the Windows Communication Foundation, a framework for building and using web services. There are lower-level APIs for working directly with web protocols. Or you can use sockets if you need very low-level control. We’ll start by discussing how to choose the most appropriate style of communication for your application, and then we’ll look at these three options in more detail.

The first step in choosing the right networking API is to decide on the nature of the communication your application requires. There are many different styles of distributed applications. Perhaps you are building a public-facing web service designed to be used by a diverse range of clients. Conversely, you might be writing client code that uses someone else’s web service. Or maybe you’re writing software that runs at both ends of the connection, but even then there are some important questions. Are you connecting a user interface to a service in a tightly controlled environment where you can easily deploy updates to the client and the server at the same time? Or perhaps you have very little control over client updates—maybe you’re selling software to thousands of customers whose own computers will connect back to your service, and you expect to have many different versions of the client program out there at any one time. Maybe it doesn’t even make sense to talk about clients and servers—you might be creating a peer-to-peer system. Or maybe your system is much simpler than that, and has just two computers talking to each other.

The variations are endless, so no single approach can work well for all systems. The next few sections will look at some common scenarios, and discuss the pros and cons of the various networking options .NET offers. Even within a specific scenario there will often be more than one way to make things work. There are no hard-and-fast rules, because each project has different requirements. So this section won’t tell you what to do—it’ll just describe the issues you’ll need to consider. Ultimately, only you can decide on the right solution for your system. We’ll start with a very common web-based scenario.

Web user interfaces have been getting smarter lately. A few years ago, most of a web application’s logic would live on the server, with client-side code in the web browser typically doing little more than making buttons light up and menus fly out in response to the mouse. But now, we expect more from our web user interfaces. Whether you use AJAX (Asynchronous JavaScript and XML), or a RIA (Rich Internet Application) technology such as Silverlight or Flash, web applications often communicate constantly with the web server, and not just when navigating between pages.

If you’re writing the server-side parts of this sort of application in C#, you will typically use ASP.NET to provide a web user interface. But what should you use for programmatic communication—the messages that flow between the web UI and the server once a page is already loaded?

WCF is a flexible choice here, because as Figure 13-1 illustrates, you can make a single set of remote services accessible to many common browser-based user interface technologies. A WCF service can be configured to communicate in several different ways simultaneously. You could use JSON (JavaScript Object Notation), which is widely used in AJAX-based user interfaces because it’s is a convenient message format for JavaScript client code. Or you could use XML-based web services. Note that using WCF on the server does not require WCF on the client. These services could be used by clients written in other technologies such as Java, as long as they also support the same web service standards as WCF.

Looking specifically at the case where your web application uses C# code on the client side, this would mean using either Silverlight or WPF. (You can put WPF in a web page by writing an XBAP—a Xaml Browser Application. This will work only if the end user has WPF installed.) If you’re using C# on both the client and the server, the most straightforward choice is likely to be WCF on both ends.

What if your server isn’t running .NET, but you still want to use .NET on the web client? There are some restrictions on WCF in this scenario. Silverlight’s version of WCF is much more limited than the version in the full .NET Framework—whereas the full version can be configured to use all manner of different protocols, Silverlight’s WCF supports just two options. There’s the so-called basic profile for web services, in which only a narrow set of features is available, and there’s a binary protocol unique to WCF, which offers the same narrow set of features but makes slightly more efficient use of network bandwidth than the XML-based basic profile. So if you want a Silverlight client to use WCF to communicate with a non-.NET web service, as Figure 13-2 illustrates, this will work only if your service supports the basic profile.

More surprisingly, similar restrictions exist with a WPF XBAP. Even though XBAPs use the full version of the .NET Framework, certain features of WCF are disabled for security purposes—client code in web browsers shouldn’t have complete freedom to connect to anywhere on the Internet, because that would make life too easy for hackers. So WCF offers only a very limited version of its services to .NET applications running inside web browsers, meaning that XBAPs have similar WCF limitations to Silverlight.

If you’re writing a Silverlight client and you want to talk to a service that does not conform to the web services basic profile, that’s not necessarily a showstopper. It just rules out WCF—you will need to use the lower-level web-based APIs instead, or even the socket APIs, depending on the service.

Note that while WCF is usually a good default choice on the server side for web applications with client-side code, there are a few cases where you might not want to use it. ASP.NET provides its own mechanism for supporting AJAX clients, and while it’s considerably less flexible than WCF, you might not need the flexibility. The simplicity of using just one framework on the server instead of two might end up looking like a better option.

There’s a subtler reason why WCF might not always be the best fit: the style of communication. If you use WCF in a web application, the communication it supports will tend to involve the following steps:

This is, in effect, a remote method invocation—it’s a way for the client to ask the server to run some code and optionally get a return value. (WCF is more flexible than this in general, but in the context of a web application, your communication patterns are constrained because clients will typically be behind a firewall.) That’s likely to be a perfectly good pattern for operations such as looking up a stock price or retrieving a weather forecast. However, if you are building a photograph browser application, this would not be a great way to retrieve pictures. You could make it work, but it’s easier to use the mechanisms already built into the web browser for downloading images—you’d almost certainly want to make the bitmaps available for download via HTTP rather than using WCF. HTML and Silverlight have UI elements that know how to render images downloaded with HTTP. Browsers are usually able to start rendering images without having to wait for the download to finish, and that’s difficult to achieve with a method invocation idiom. And by using normal HTTP image download, you’d also get to take advantage of standard HTTP caching in your web browser and any caching proxies you may be using. Plain old HTTP works better here than trying to fetch a bitmap using something resembling a method call.

More generally, if the information your client code works with looks like a set of resources that might be identified with URIs (Uniform Resource Identifiers; for instance, http://oreilly.com/) and accessed via HTTP you might want to stick with ordinary HTTP rather than using WCF. Not only do you get the benefits of normal HTTP caching when reading data, but it may also simplify security—you might be able to take whatever mechanism you use to log people into the website and secure access to web pages, and use it to secure the resources you fetch programmatically.

Using WCF typically requires less effort than designing a RESTful service—you can get up and running with a good deal less thought and forward planning (although you might not consider a lack of thought and planning to be a good thing for your particular application). But if the communication you require with your server doesn’t sound like it fits well into a method-call-like style, you’ll probably want to consider alternatives to WCF.

Occasionally, neither WCF nor plain HTTP will be the best approach when connecting a web UI to a service. With Silverlight, you have the option to use TCP or UDP sockets from the web browser. (The UDP support is somewhat constrained. Silverlight 4, the current version at the time of writing this, only supports UDP for multicast client scenarios.) This is a lot more work, but it can support more flexible communication patterns—you’re not constrained to the request/response style offered by HTTP. Games and chat applications might need this flexibility, because it provides a way for the server to notify the client anytime something interesting happens. Sockets can also offer lower communication latency than HTTP, which can be important for games.

Fashionable though web applications are, they’re not the only kind of distributed system. Traditional Windows applications built with WPF or Windows Forms are still widely used, as they can offer some considerable advantages over web applications for both users and developers. Obviously, they’re an option only if all your end users are running Windows, but for many applications that’s a reasonable assumption. Assuming clients are running Windows, the main downside of this kind of application is that it’s hard to control deployment compared to a web application. With web applications, you only have to update an application on the server, and all your clients will be using the new version the next time they request a new page.

To update a classic Windows application, you need to somehow get a new version of the program onto the end users’ machines. Since it’s rarely practical to install a new version on every single user’s machine simultaneously, you need to handle the possibility of having several different versions of the client software all trying to talk to your server. The extent to which this can cause problems will depend on how much control you have over the client computers.

Some applications are deployed in tightly controlled environments. For example, suppose you’re writing a line-of-business application in WPF that will only ever be deployed to machines owned by your business. If your IT department has an iron grip on the company’s computers, you might be able to exert considerable control over what versions of your application are out there. Network administrators could forcibly upgrade users to the latest version. So new versions might overlap with old versions for only a day or so. You could even go further and arrange for your application to check for updates and refuse to continue running when a newer version is available.

This is a happy situation for a developer, because it makes it much easier to introduce changes to your server. Chances are that at some point you’ll want to add new services to support new features in your application. You might also want to modify existing services, which is usually more problematic than completely new features—if you’re using WCF, it’s not easy to modify the way an existing service works without breaking that service for older clients. It’s possible, but it’s hard, and it’s often easier to run multiple versions of the service simultaneously during the transition period. The nice thing about having sufficient control to remove old versions of the application is that you can know when you’ve reached the end of a transition period and can shut down the older version of the service. This won’t be the case if you can’t force that sort of change on the client.

If your application’s customers don’t all work for your company, life becomes more complex, because it’s harder to force upgrades on your customers. It’s not impossible—for example, Microsoft’s Windows Live Messenger program occasionally tells you that if you don’t upgrade you won’t be able to carry on using the service. Mind you, it’s a free service, so it gets to dictate its terms of use; you might find that paying customers won’t put up with that, insisting that the product they’ve bought carries on working without needing to install regular upgrades.

The implication is that you might need to support old versions of your service indefinitely. At this point, WCF might not look like such a good choice. One of the attractive features of WCF is that it does a lot of work for you under the covers, but that’s a double-edged sword—it works really well when both ends of the connection evolve simultaneously, but it can become a burden over time if the two ends do not move forward in tandem. If you want a service to be able to evolve while the client does not, you end up needing to understand exactly how WCF presents your service, and how the changes you have in mind might affect its operation. For example, if you decide that a method in your service requires an extra argument, what happens when an old client invokes the operation without that new argument? In practice, it might actually be easier just to work directly with HTTP and XML, because that way you have complete control over what messages go across the network.

That’s not to say that WCF is definitely the wrong choice here. You could deal with the problem described by maintaining multiple versions of the service, or by dropping down to WCF’s lower-level messaging API, for example. But the trade-off between WCF and HTTP is altered by the nature of your deployment. In a tightly controlled deployment, WCF is likely to be a good choice, but when you have less control, the lower-level APIs can start to look like they’re worth the extra effort.

Regardless of how much control you have over deployment, as with the web application case there are some specialized scenarios in which neither WCF-based web services nor web APIs are the best fit. If you need communication patterns that don’t fit well with HTTP, be aware that with this style of application, you can use the full range of communication styles offered by WCF—as we’ll see, it supports more than just the typical web communication patterns. This means that sockets are an even more unusual choice in this scenario, and would typically be useful only if you need very precise control over the way in which messages are constructed and delivered.

You won’t necessarily write the code at both ends of a connection. You might build a .NET client which talks to a web service provided by someone else. For example, you could write a WPF frontend to an online social media site such as Twitter, or a Silverlight client that accesses an external site such as Digg.

In this case, your choice of communication technology will be determined largely by the service you’re connecting to. If it presents information in a way that WCF is able to consume, use WCF. How would you know that this is the case? You could try asking the service provider’s support staff if their service works with WCF, but if they’re not sure, it’ll be down to the nature of the service. If your service provider uses the so-called WS-* family of web service standards, there’s a good chance WCF will be able to talk to the service.

If WCF works in your scenario, that’s great, but when it is not an option, use .NET’s HTTP-based APIs. Unless, of course, the service in question is not HTTP-based, and requires you to work directly with TCP or UDP, in which case you would use sockets. In short, you’re at the mercy of the server, and you’ll just have to pick whichever option happens to work.

Note that because Silverlight’s version of WCF is considerably more limited than the full .NET Framework version, a Silverlight client is more likely to have to drop down to the HTTP APIs than a full .NET client.

If you are writing a web service in .NET that you would like to be accessible to client programs written by people other than you, the choice of technology will be determined by two things: the nature of the service and the demands of your clients.[26] If it’s something that fits very naturally with HTTP—for example, you are building a service for retrieving bitmaps—writing it as an ordinary ASP.NET application may be the best bet (in which case, refer to Chapter 21). But for services that feel more like a set of remotely invocable methods, WCF is likely to be the best bet. You can configure WCF to support a wide range of different network protocols even for a single service, thus supporting a wide range of clients.

As with the other application types, you would use sockets only if your application has unusual requirements that cannot easily be met using the communication patterns offered by HTTP.

So having looked at some common scenarios and seen which communication options are more or less likely to fit, let’s look at how to use those options.



[26] More accurately, the demands to which you feel inclined to accede.