Creating a Server with .NET Socket Programming

In this day and age of HTTP and Web browsers, you might thing that the only network protocol you need to know these days is "HTTP", but there are still a lot of places where raw socket-level programming has an advantage.

For example, there are still a lot of POP3 and IMAP mail systems out there, and many online games use their own custom protocols over a custom socket.

What Exactly Is a Socket?

Imagine your computer network is a bit like a series of interconnected water pipes. Some of those pipes lead to certain parts, like a hot water tank or a waste water disposal outlet.

Now, imagine that you fill your sink with hot water do some washing, then pull the plug out and drain the dirty water away.

In essence, you've just connected to a "Hot water Port," received some hot water, and then connected to a "Waste Water Port," and sent it elsewhere.

A port, therefore, is a connection to a given service at a given location that provides something via that service.

As you may be aware, your PC has a unique address, called an IP address. How that address is set up is a matter of a more in-depth article, but you can be almost certain that you'll have an address called "The Loopback Address," or "Localhost," as it's more commonly known. This address is usually written as 127.0.0.1 and means "The IP address of this machine I'm currently running on."

If you have a public IP address—that is, if you have an IP address that other computers on the Internet can see, then that could be something like 188.125.73.108 (which is the public IP address of www.yahoo.co.uk), you might also have a local network address such as 192.168.0.1, which your office or router might hand out to you for use inside your network.

Whichever address you have, they all mean the same thing: a location to find your computer at.

Ports are then "Opened" on these machines to provide "Services" (just like the hot water example above), different services use different ports, with port numbers below 1024 being known as "The Well-known Port range."

When you talk to a Web server, for example, your browser by default will talk to port number 80, because port number 80 is the "Well-known port for HTTP." If you use SSH, that will open and listen on port 22 which is the "Well-known port for SSH."

An IP address on any PC can have a maximum of 65535 ports opened and available with services listening for requests, for user code (that is, not code running as a service or admin) you'll normally need to be 1025 or higher.

If you run a command terminal and type "netstat -an" followed by return, you should see something similar to this:

Socket1
Figure 1: Output from Netstat command line tool

You can see on the machine I'm typing this on there are a number of services running, listening on a number of different ports, and you can also see the first entry in the list is port 80, due to the fact that I have IIS7 running on this machine.

You also can see UDP services. UDP is like TCP but doesn't have the reliability that TCP does. For the rest of this article, we'll concentrate on TCP, and look at UDP in a future article.

Writing a .NET Socket Server

For this example, we're just going to write a simple console mode program that waits and listens for one connection at a time. It will listen on port 5000 and return a message whenever anything connects to it.

Fire up Visual Studio, and start a desktop/console mode application.

The quickest way to get started with .NET sockets is via the use of the "TcpListener" class, and getting started is a simple as the following code.

using System;
using System.Net;
using System.Net.Sockets;

namespace sockets_blogpost
{
   class Program
   {
      static void Main()
      {
         TcpListener myListner = new
            TcpListener(new IPAddress(0x00000000),
            5000);
         myListner.Start();

         Console.ReadLine();
      }
   }
}

The above will start listening on 0.0.0.0 port 5000, but won't do much just yet beccause we've not yet programmed it to respond to incoming requests.

Before we proceed, however, just a little note about the IP address.

You'll note that we've specified the address as "0x00000000" in the example above.

This is known as "The Long address format." Each IP address in the version 4 TCP scheme, consists of 4 bytes. Each byte is a maximum of 255 and a minimum of 0, which means IP addresses can go from 0.0.0.0 to 255.255.255.255 in theory.

In practice, these ranges are divided up into blocks owned by different companies or assigned to different purposes and you can't just pick and choose what you want to use.

To convert an IP address to its long format, you need to change each byte to its hexadecimal representation, and then concatenate them in the correct order.

You can do this by hand if you want to, but on some platforms you might have to be aware of the byte order, so it's better to use the built-in IP address routines.

In the example above, we could, for instance, have done the following:

TcpListener myListner = new
   TcpListener(IPAddress.Any, 5000);

Or

TcpListener myListner = new
   TcpListener(IPAddress.Parse("0.0.0.0"),
   5000);

all of which would have had the same effect.

If you wanted to listen to a specific address, rather than the first or any found on the machine, then you could simply use:

TcpListener myListner = new
   TcpListener(IPAddress.Parse("192.168.10.5"),
   5000);

Or

TcpListener myListner = new
   TcpListener(IPAddress.Parse("127.0.0.1"),
   5000);

This would make your service listen on the two numbered IP addresses only.

At this point, you should be able to actually run your service and have it listen, depending on your platform and how you're set up you might also see the following when you do:

Socket2
Figure 2: The Windows firewall asking you if your program is allowed socket access

For my purposes, I've allowed it access. If you're going to be using specific ports often, you might want to set up a rule to stop the firewall asking you for permission all the time.

If you perform another "Netstat -na" command at this point, you should see your application listening:

Socket3
Figure 3: Netstat showing our app listening

If we now update our Main method as follows:

using System.IO;
using System.Net;
using System.Net.Sockets;

namespace sockets_blogpost
{
   class Program
   {
      static void Main()
      {
         bool quit = false;

         // Listen on 0.0.0.0 (Any address available)
         // and open port 5000
         TcpListener myListner = new
            TcpListener(new IPAddress(0x00000000), 5000);
         myListner.Start();

         while(!quit)
         {
            Socket mySocket = myListner.AcceptSocket();
            Stream myStream = new NetworkStream(mySocket);
            StreamReader reader = new StreamReader(myStream);
            StreamWriter writer = new StreamWriter(myStream)
               {AutoFlush = true};
            string text = reader.ReadLine();
            if(text != null && text.ToLower() == "quit")
            {
               quit = true;
            }
            writer.WriteLine("Hello I'm a TCP server");
            myStream.Close();
            mySocket.Close();
         }
      }
   }
}

Our server will now accept and respond to commands sent to it.

If you run your server and open a terminal program such as PuTTy (downloadable from http://www.chiark.greenend.org.uk/~sgtatham/putty/) and send some text to port 5000, you should see something like the following:

Socket4
Figure 4: PuTTy responding that it's listening

If you enter the word "quit" and press Return, your server should exit and return you back to Visual Studio.

At this point, you have a single client server that can only process one blocking client at once.

In reality, the main loop in the centre should probably be pushed out into a different thread so that once the connection is being serviced your main server can go back and wait for more connections.

Got a tricky class you want to know more about, or just have some tips to add to the toolbox? Feel free to come find me on Twitter as @shawty_ds and let me know your thoughts.



About the Author

Peter Shaw

As an early adopter of IT back in the late 1970s to early 1980s, I started out with a humble little 1KB Sinclair ZX81 home computer. Within a very short space of time, this small 1KB machine became a 16KB Tandy TRS-80, followed by an Acorn Electron and, eventually, after going through many other different machines, a 4MB, ARM-powered Acorn A5000. After leaving school and getting involved with DOS-based PCs, I went on to train in many different disciplines in the computer networking and communications industries. After returning to university in the mid-1990s and gaining a Bachelor of Science in Computing for Industry, I now run my own consulting business in the northeast of England called Digital Solutions Computer Software, Ltd. I advise clients at both a hardware and software level in many different IT disciplines, covering a wide range of domain-specific knowledge—from mobile communications and networks right through to geographic information systems and banking and finance.

Related Articles

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date