Code Listings

Chapter 15: Networking

IP Addresses:

IPAddress a1 = new IPAddress (new byte[] { 101, 102, 103, 104 });
IPAddress a2 = IPAddress.Parse ("101.102.103.104");
Console.WriteLine (a1.Equals (a2));                     // True
Console.WriteLine (a1.AddressFamily);                   // InterNetwork

IPAddress a3 = IPAddress.Parse
  ("[3EA0:FFFF:198A:E4A3:4FF2:54fA:41BC:8D31]");
Console.WriteLine (a3.AddressFamily);   // InterNetworkV6
IPAddress a = IPAddress.Parse ("101.102.103.104");
IPEndPoint ep = new IPEndPoint (a, 222);           // Port 222
Console.WriteLine (ep.ToString());                 // 101.102.103.104:222

URIs:

Uri info = new Uri ("http://www.domain.com:80/info/");
Uri page = new Uri ("http://www.domain.com/info/page.html");

Console.WriteLine (info.Host);     // www.domain.com
Console.WriteLine (info.Port);     // 80
Console.WriteLine (page.Port);     // 80  (Uri knows the default HTTP port)

Console.WriteLine (info.IsBaseOf (page));         // True
Uri relative = info.MakeRelativeUri (page);
Console.WriteLine (relative.IsAbsoluteUri);       // False
Console.WriteLine (relative.ToString());          // page.html

Simple use of WebClient:

using (WebClient wc = new WebClient())
{
  wc.Proxy = null;
  wc.DownloadFile ("http://www.albahari.com/nutshell/code.html",
                   "code.html");
}
System.Diagnostics.Process.Start ("code.html");

Simple use of WebRequest / WebResponse:

WebRequest req = WebRequest.Create 
                ("http://www.albahari.com/nutshell/code.html");
req.Proxy = null;
using (WebResponse res = req.GetResponse())
using (Stream s = res.GetResponseStream())
using (StreamReader sr = new StreamReader(s))
  File.WriteAllText ("code.html", sr.ReadToEnd());

System.Diagnostics.Process.Start ("code.html");

Proxies:

// Create a WebProxy with the proxy's IP address and port. You can
// optionally set Credentials if the proxy needs a username/password.

WebProxy p = new WebProxy ("192.178.10.49", 808);
p.Credentials = new NetworkCredential ("username", "password");
// or:
p.Credentials = new NetworkCredential ("username", "password", "domain");

using (WebClient wc = new WebClient())
{
  wc.Proxy = p;
  ...
}

// Same procedure with a WebRequest object:
WebRequest req = WebRequest.Create ("...");
req.Proxy = p;

Authentication:

using (WebClient wc = new WebClient())
{
  wc.Proxy = null;
  wc.BaseAddress = "ftp://ftp.albahari.com/incoming/";

  // Authenticate, then upload and download a file to the FTP server.
  // The same approach also works for HTTP and HTTPS.

  string username = "user";
  string password = "play";
  wc.Credentials = new NetworkCredential (username, password);

  wc.DownloadFile ("guestbook.txt", "guestbook.txt");
  
  string data = "Hello from " + Environment.UserName + "!\r\n";
  File.AppendAllText ("guestbook.txt", data);

  wc.UploadFile ("guestbook.txt", "guestbook.txt");
}

CredentialCache:

CredentialCache cache = new CredentialCache();
Uri prefix = new Uri ("http://exchange.mydomain.com");
cache.Add (prefix, "Digest",  new NetworkCredential ("joe", "passwd"));
cache.Add (prefix, "Negotiate", new NetworkCredential ("joe", "passwd"));

WebClient wc = new WebClient();
wc.Credentials = cache;
...

Concurrency without asynchronous event methods:

using System;
using System.Net;
using System.Threading;

class ThreadTest
{
  static void Main()
  {
    new Thread (Download).Start();
    Console.WriteLine ("I'm still here while the download's happening!");
    Console.ReadLine();
  }

  static void Download()
  {
    using (WebClient wc = new WebClient())
      try
      {
        wc.Proxy = null;
        wc.DownloadFile ("http://www.oreilly.com", "oreilly.html");
        Console.WriteLine ("Finished!");
      }
      catch (Exception ex)
      {
        // Process exception...
      }
  }
}

Exception handling with WebClient/WebRequest/WebResponse:

using (WebClient wc = new WebClient())
  try
  {
    wc.Proxy = null;
    string s = wc.DownloadString ("http://www.albahari.com/notthere");
  }
  catch (WebException ex)
  {
    if (ex.Status == WebExceptionStatus.NameResolutionFailure)
      Console.WriteLine ("Bad domain name");
    else if (ex.Status == WebExceptionStatus.ProtocolError)
    {
      HttpWebResponse response = (HttpWebResponse) ex.Response;
      Console.WriteLine (response.StatusDescription);      // "Not Found"
      if (response.StatusCode == HttpStatusCode.NotFound)
        Console.WriteLine ("Not there!");                  // "Not there!"
    }
    else throw;
  }

HTTP headers:

using (WebClient wc = new WebClient())
{
  wc.Proxy = null;
  wc.Headers.Add ("CustomHeader", "JustPlaying/1.0");
  wc.DownloadString ("http://www.oreilly.com");

  foreach (string name in wc.ResponseHeaders.Keys)
    Console.WriteLine (name + "=" + wc.ResponseHeaders [name]);
}

HTTP query strings:

using (WebClient wc = new WebClient())
{
  wc.Proxy = null;
  wc.QueryString.Add ("q", "WebClient");     // Search for "WebClient"
  wc.QueryString.Add ("hl", "fr");           // Display page in French
  wc.DownloadFile ("http://www.google.com/search", "results.html");
  System.Diagnostics.Process.Start ("results.html");
}

Uploading form data with WebClient:

using (WebClient wc = new WebClient())
{        
  wc.Proxy = null;
  
  var data = new System.Collections.Specialized.NameValueCollection();
  data.Add ("searchtextbox", "webclient");
  data.Add ("searchmode", "simple");

  byte[] result = wc.UploadValues ("http://safari.oreilly.com/search",
                                   "POST", data);

  System.IO.File.WriteAllBytes ("SearchResults.html", result);
  System.Diagnostics.Process.Start ("SearchResults.html");
}

Uploading form data with WebRequest:

WebRequest req = WebRequest.Create ("http://safari.oreilly.com/search");

req.Proxy = null;
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";

string reqString
  = "searchtextbox=webclient&searchmode=simple";
byte[] reqData = Encoding.UTF8.GetBytes (reqString);
req.ContentLength = reqData.Length;

using (Stream reqStream = req.GetRequestStream())
  reqStream.Write (reqData, 0, reqData.Length);

using (WebResponse res = req.GetResponse())
using (Stream resSteam = res.GetResponseStream())
using (StreamReader sr = new StreamReader (resSteam))
  File.WriteAllText ("SearchResults.html", sr.ReadToEnd());

System.Diagnostics.Process.Start ("SearchResults.html");

Cookies:

CookieContainer cc = new CookieContainer();

var request = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
request.Proxy = null;
request.CookieContainer = cc;
using (var response = (HttpWebResponse) request.GetResponse())
{
  foreach (Cookie c in response.Cookies)
  {
    Console.WriteLine (" Name:   " + c.Name);
    Console.WriteLine (" Value:  " + c.Value);
    Console.WriteLine (" Path:   " + c.Path);
    Console.WriteLine (" Domain: " + c.Domain);
  }
  // Read response stream...
}

Forms authentication:

string loginUri = "http://www.webshots.com/login";
string username = "username";
string password = "password";
string reqString = "username=" + username + "&password=" + password;
byte[] requestData = Encoding.UTF8.GetBytes (reqString);

CookieContainer cc = new CookieContainer();
var request = (HttpWebRequest)WebRequest.Create (loginUri);
request.Proxy = null;
request.CookieContainer = cc;
request.Method = "POST";

request.ContentType = "application/x-www-form-urlencoded";    
request.ContentLength = requestData.Length;
using (Stream s = request.GetRequestStream())
  s.Write (requestData, 0, requestData.Length);

using (var response = (HttpWebResponse) request.GetResponse())
  foreach (Cookie c in response.Cookies)
    Console.WriteLine (c.Name + " = " + c.Value);

SSL:

using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
…
static void ConfigureSSL()
{
  ServicePointManager.ServerCertificateValidationCallback = CertChecker;
}

static bool CertChecker (object sender, X509Certificate certificate,
                         X509Chain chain, SslPolicyErrors errors)
{
  // Return true if you're happy with the certificate
  …
}

Writing a simple HTTP server:

static void Main()
{
  new System.Threading.Thread (Listen).Start(); // Run server in parallel.
  Thread.Sleep (500);                           // Wait half a second.
  
  using (WebClient wc = new WebClient())        // Make a client request.
    Console.WriteLine (wc.DownloadString     
      ("http://localhost:51111/MyApp/Request.txt"));
}

static void Listen()
{
  HttpListener listener = new HttpListener();
  listener.Prefixes.Add ("http://localhost:51111/MyApp/");  // Listen on
  listener.Start();                                         // port 51111.

  // Wait for a client request:
  HttpListenerContext context = listener.GetContext();

  // Respond to the request:
  string msg = "You asked for: " + context.Request.RawUrl;
  context.Response.ContentLength64 = Encoding.UTF8.GetByteCount (msg);
  context.Response.StatusCode = (int) HttpStatusCode.OK;

  using (Stream s = context.Response.OutputStream)
  using (StreamWriter writer = new StreamWriter (s))
    writer.Write (msg);

  listener.Stop();
}

Writing a blocking pooled HTTP server:

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;

class WebServer
{
  HttpListener _listener;
  string _baseFolder;      // Your web page folder.

  public WebServer (string uriPrefix, string baseFolder)
  {
    System.Threading.ThreadPool.SetMaxThreads (50, 1000);
    System.Threading.ThreadPool.SetMinThreads (50, 50);
    _listener = new HttpListener();
    _listener.Prefixes.Add (uriPrefix);
    _baseFolder = baseFolder;
  }

  public void Start()          // Run this on a separate thread, as
  {                            // we did before.
    _listener.Start();
    while (true)
      try
      {
        HttpListenerContext request = _listener.GetContext();
        ThreadPool.QueueUserWorkItem (ProcessRequest, request);
      }
      catch (HttpListenerException)     { break; }   // Listener stopped.
      catch (InvalidOperationException) { break; }   // Listener stopped.
  }

  public void Stop() { _listener.Stop(); }

  void ProcessRequest (object listenerContext)
  {
    try
    {
      var context = (HttpListenerContext) listenerContext;
      string filename = Path.GetFileName (context.Request.RawUrl);
      string path = Path.Combine (_baseFolder, filename);
      byte[] msg;
      if (!File.Exists (path))
      {
        context.Response.StatusCode = (int) HttpStatusCode.NotFound;
        msg = Encoding.UTF8.GetBytes ("Sorry, that page does not exist");
      }
      else
      {
        context.Response.StatusCode = (int) HttpStatusCode.OK;
        msg = File.ReadAllBytes (path);
      }
      context.Response.ContentLength64 = msg.Length;
      using (Stream s = context.Response.OutputStream)
        s.Write (msg, 0, msg.Length);
    }
    catch (Exception ex) { Console.WriteLine ("Request error: " + ex); }
  }
}
static void Main()
{
  // Listen on the default port (80), serving files in e:\mydocs\webroot:
  var server = new WebServer ("http://localhost/", @"e:\mydocs\webroot");

  // Start the server on a parallel thread:
  new System.Threading.Thread (server.Start).Start();  

  Console.WriteLine ("Server running... press Enter to stop");
  Console.ReadLine();
  server.Stop();
}

Using FTP:

using (WebClient wc = new WebClient())
{
  wc.Proxy = null;
  wc.Credentials = new NetworkCredential ("user", "play");
  wc.BaseAddress = "ftp://ftp.albahari.com/incoming/";

  wc.UploadString ("tempfile.txt", "hello!");
  Console.WriteLine (wc.DownloadString ("tempfile.txt"));   // hello!
}

FTP ListDirectory:

var req = (FtpWebRequest) WebRequest.Create (
                          "ftp://ftp.albahari.com/incoming");
req.Proxy = null;
req.Credentials = new NetworkCredential ("user", "play");

req.Method = WebRequestMethods.Ftp.ListDirectory;

using (WebResponse resp = req.GetResponse())
using (StreamReader reader = new StreamReader (resp.GetResponseStream()) )
  Console.WriteLine (reader.ReadToEnd());

FTP GetFileSize:

var req = (FtpWebRequest) WebRequest.Create (
                          "ftp://ftp.albahari.com/incoming/tempfile.txt");
req.Proxy = null;
req.Credentials = new NetworkCredential ("user", "play");

req.Method = WebRequestMethods.Ftp.GetFileSize;

using (WebResponse resp = req.GetResponse())
  Console.WriteLine (resp.ContentLength);             // 6

FTP LastModified:

req.Method = WebRequestMethods.Ftp.GetDateTimestamp;

using (var resp = (FtpWebResponse) req.GetResponse() )
  Console.WriteLine (resp.LastModified);

FTP Rename:

var req = (FtpWebRequest) WebRequest.Create (
                          "ftp://ftp.albahari.com/incoming/tempfile.txt");
req.Proxy = null;
req.Credentials = new NetworkCredential ("user", "play");

req.Method = WebRequestMethods.Ftp.Rename;
req.RenameTo = "deleteme.txt";

req.GetResponse().Close();        // Perform the rename

FTP DeleteFile:

var req = (FtpWebRequest) WebRequest.Create (
                          "ftp://ftp.albahari.com/incoming/deleteme.txt");
req.Proxy = null;
req.Credentials = new NetworkCredential ("user", "play");

req.Method = WebRequestMethods.Ftp.DeleteFile;

req.GetResponse().Close();        // Perform the deletion

Sending Mail with SmtpClient:

SmtpClient client = new SmtpClient();
client.Host = "mail.myisp.net";
client.Send ("from@adomain.com", "to@adomain.com", "subject", "body");

Mail attachments:

SmtpClient client = new SmtpClient();
client.Host = "mail.myisp.net";
MailMessage mm = new MailMessage();

mm.Sender = new MailAddress ("kay@domain.com", "Kay");
mm.From   = new MailAddress ("kay@domain.com", "Kay");
mm.To.Add  (new MailAddress ("bob@domain.com", "Bob"));
mm.CC.Add  (new MailAddress ("dan@domain.com", "Dan"));
mm.Subject = "Hello!";
mm.Body = "Hi there. Here's the photo!";
mm.IsBodyHtml = false;
mm.Priority = MailPriority.High;

Attachment a = new Attachment ("photo.jpg",
                               System.Net.Mime.MediaTypeNames.Image.Jpeg);
mm.Attachments.Add (a);

client.Send (mm);

TCP ping-pong:

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

class TcpDemo
{
  static void Main()
  {
    new Thread (Server).Start();       // Run server method concurrently.
    Thread.Sleep (500);                // Give server time to start.
    Client();
  }

  static void Client()
  {
    using (TcpClient client = new TcpClient ("localhost", 51111))            
    using (NetworkStream n = client.GetStream())
    {
      BinaryWriter w = new BinaryWriter (n);
      w.Write ("Hello");
      w.Flush();
      Console.WriteLine (new BinaryReader (n).ReadString());
    }
  }

  static void Server()     // Handles a single client request, then exits.
  {
    TcpListener listener = new TcpListener (IPAddress.Any, 51111);
    listener.Start();
    using (TcpClient c = listener.AcceptTcpClient())
    using (NetworkStream n = c.GetStream())
    {
      string msg = new BinaryReader (n).ReadString();
      BinaryWriter w = new BinaryWriter (n);
      w.Write (msg + " right back!");
      w.Flush();                      // Must call Flush because we're not
    }                                 // disposing the writer.
    listener.Stop();
  }
}

Receiving POP3 mail:

static void Receive()
{
  using (TcpClient client = new TcpClient ("mail.isp.com ", 110))
  using (NetworkStream n = client.GetStream())
  {
    ReadLine (n);                             // Read the welcome message.
    SendCommand (n, "USER username");
    SendCommand (n, "PASS password");
    SendCommand (n, "LIST");                  // Retrieve message IDs
    List<int> messageIDs = new List<int>();
    while (true)
    {
      string line = ReadLine (n);             // e.g.  "1 1876"
      if (line == ".") break;
      messageIDs.Add (int.Parse (line.Split (' ')[0] ));   // Message ID
    }

    foreach (int id in messageIDs)         // Retrieve each message.
    {
      SendCommand (n, "RETR " + id);
      string randomFile = Guid.NewGuid().ToString() + ".eml";
      using (StreamWriter writer = File.CreateText (randomFile))
        while (true)
        {
          string line = ReadLine (n);      // Read next line of message.
          if (line == ".") break;          // Single dot = end of message.
          if (line == "..") line = ".";    // "Escape out" double dot.
          writer.WriteLine (line);         // Write to output file.
        }
      SendCommand (n, "DELE " + id);       // Delete message off server.
    }
    SendCommand (n, "QUIT");
  }
}

static string ReadLine (Stream s)
{
  List<byte> lineBuffer = new List<byte>();
  while (true)
  {
    int b = s.ReadByte();
    if (b == 10 || b < 0) break;
    if (b != 13) lineBuffer.Add ((byte)b);
  }
  return Encoding.UTF8.GetString (lineBuffer.ToArray());
}

static void SendCommand (Stream stream, string line)
{
  byte[] data = Encoding.UTF8.GetBytes (line + "\r\n");
  stream.Write (data, 0, data.Length);
  string response = ReadLine (stream);
  if (!response.StartsWith ("+OK"))
    throw new Exception ("POP Error: " + response);
}
C# 12 in a Nutshell
Buy from amazon.com Buy print or Kindle edition
Buy from ebooks.com Buy PDF edition
Buy from O'Reilly Read via O'Reilly subscription