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);
}