Friday, February 24, 2012

C# Socket Hello World Example

Often a better understanding of a programming concept can be had by looking at a bare bones example.  Below is such an example of using .NET sockets to establish communication between a server and one or more clients that does without the fluff.  The server code:

class Server
{
 static void Main(string[] args)
 {
  // create the listener socket
  IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
  Socket serverSocket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 52000);
  serverSocket.Bind(ipEndPoint);
  serverSocket.Listen(100);

  AutoResetEvent connectedSignal = new AutoResetEvent(false);
  // establish connections with clients
  while (true)
  {
   serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), new Tuple<Socket, AutoResetEvent>(serverSocket, connectedSignal));
   // wait here until we've established a connection
   connectedSignal.WaitOne();
  }
 }

 // asynchronous callback to accept a connection
 static void AcceptCallback(IAsyncResult acceptAsynchResult)
 {
  var connectionObject = (Tuple<Socket, AutoResetEvent>)acceptAsynchResult.AsyncState;
  // signal to the loop in Main that we've established a connection
  connectionObject.Item2.Set();

  Socket receiveSocket = connectionObject.Item1.EndAccept(acceptAsynchResult);

  // receive the data
  var readData = new Tuple<Socket, byte[]>(receiveSocket, new byte[1024]);
  receiveSocket.BeginReceive(readData.Item2, 0, readData.Item2.Length, SocketFlags.None, new AsyncCallback(ReadCallback), readData);
 }

 // asynchronous callback to read socket data
 static void ReadCallback(IAsyncResult readAsyncResult)
 {
  var readData = (Tuple<Socket, byte[]>)readAsyncResult.AsyncState;

  // handle SocketException where SocketErrorCode == SocketError.ConnectionReset 
  // to gracefully handle sudden client disconnects
  int read = readData.Item1.EndReceive(readAsyncResult);

  if (read > 0)
  {
   // write received data to the console
   Console.WriteLine(Encoding.UTF8.GetString(readData.Item2, 0, read));
   // set up to receive more data
   readData.Item1.BeginReceive(readData.Item2, 0, readData.Item2.Length, SocketFlags.None, new AsyncCallback(ReadCallback), readData);
  }
 }
}

The server will establish connections as often as their are clients.  An AutoResetEvent is used to signal when the server has established a connection with a client and should ready itself for another connection.  The client:

IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 52000);
clientSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Connect(ipe);

clientSocket.Send(Encoding.UTF8.GetBytes("Hello World"));
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Disconnect(false);

Adding blogger syntax highlighting

Blogger doesn't support syntax highlighting for code by default - you have to add it.  But it's a snap with the instructions here: http://heisencoder.net/2009/01/adding-syntax-highlighting-to-blogger.html.  Plus, it's all inline.  There is a newer version, but it requires you add a link to javascript at alexgorbatchev.com which I wanted to avoid if I could.

Wednesday, February 22, 2012

PowerShell's Read-Host returns immediately

If you're like me and to save time copy and paste a command line you use repeatedly into the PowerShell command window, you could cause issues for the Read-Host cmdlet.  For example, say I pasted these commands:

    cd c:\somedirectory
    .\MyScript.ps1 someparameters

If I, when I copied that text, included the trailing carriage return/line feed at the end, that would cause those two commands to execute the instant I pasted them into the PowerShell window.  The problem is that if MyScript.ps1 contains a call to Read-Host it will trick it into thinking the enter key was pressed, when it was not, and your first Read-Host will fail to block.

To get around this I either 1) make sure I manually enter the command or 2) make sure I don't include the trailing newline when I copy the command text.

System.NotSupportedException instantiating a .NET IpcChannel

Instantiating a System.Runtime.Remoting.Channels.Ipc.IpcChannel was throwing a System.NotSupportedException.  In Visual Studio, hovering over the exception showed it to be a plain System.Exception containing a property _COMPlusExceptionCode with a value of -532462766.  I've also seen a RemotingException, "Failed to create an IPC Port: Access is denied", so the error message you receive may be inconsistent as well.

The problem appears to be a lingering, identical IpcChannel within the same process, even one that is no longer registered but has not yet been completely cleaned up.  The _COMPlusExceptionCode threw me off for a while, but it appears a solution has been found here:

http://social.msdn.microsoft.com/Forums/en/netfxremoting/thread/d154e4a9-3e31-41a5-944c-db867ca77e9e

However this solution will permit multiple connections to be open with potentially undesirable consequences.  A loop that makes several attempts to create the IpcChannel may be a more appropriate solution.

Wednesday, February 15, 2012

Transactions as an Aspect

Documents that introduce AOP use the same examples when describing its practical applications.  The first two, in this order, are always:
  • Logging
  • Transactions
And indeed, you can treat transactions, in particular database transactions, as an aspect.  Your business object is kept blissfully unaware that it is wrapped by a proxy that is executing it within a transaction.

However, in multi-threaded environments, business object must also perform synchronization.  That is, when performing an operation the business object must guarantee it's not accessing shared data with itself on a different thread.  To prevent this, it must acquire object locks.  Since the locks are private (as they should be, to preserve encapsulation) to the object in question, and because how or what locks are acquired may change depending upon the method parameters and/or logic, it is up to each individual public object operation to perform the locking.

When an operation on an object with a transaction aspect applied the transaction would start first, then the object locks would be acquired.  This is a problem because you never want to start a database transaction first.  If an object lock takes longer to acquire than a database transaction is long the operation will fail.  Instead, we want to acquire object locks first, then begin the transaction.

This would seem to indicate that transactions can't be represented as an aspect.  However, we won't give up quite yet.  One could argue that the synchronization I described could also be captured as an aspect.  You could apply both aspects to the business object so long as you ensure the synchronization aspect is a layer above the transaction aspect.  But can the synchronization aspect have enough knowledge to understand what locks to acquire?  Would it not have to duplicate logic already present in the business object?  How would this fit into a design that cached data access which had to acquire its own locks?  Would we not be setting ourselves up for deadlocks?

Documenting Code with Code

On a regulated software project, especially one regulated by a government body, design documentation is a must.  It proves that designs were thought out and not developed in an ad hoc fashion, and captures key considerations made when the software was developed so that future developers, who may not have been part of the original project, are able to safely perform maintenance.

There are two popular methods for creating design documentation.  One method is to use tools like Word and Visio to manually create documentation.  This method gives the writer absolute control over the contents of the document.  However, this document will likely repeat documentation already found in your C# XML comments.  Also, creating Visio diagrams by hand can be tedious and time consuming.  And just because the documentation is being written doesn't mean the design won't change.  In many Agile environments, hand written documentation will likely be obsolete the minute it is published.

Another method involves using a documentation generation tool, like doxygen for example.  Tools like this extract documentation from code and format it as html, a pdf, etc.  Because documentation can be generated on the fly, it will always be relevant.  However, its really only good as reference documentation -- without sequence diagrams or textual design summaries providing context it would be difficult for a developer to understand the code for maintenance purposes.  For those tools that can automatically generate object model diagrams and sequence diagrams from code, how will it know what level of detail is sufficient?  How can it possibly have enough understanding of the code to diagram things into meaningful compartments.  To get all of the benefits, but none of the drawbacks, a documentation tool that resides somewhere in the middle is needed.

Instead of either of the previous methods, build a documentation generation framework where documentation is generated from code.  More precisely, the documentation IS code.  Think about it:
  • Don't ever hand draw diagrams - use code to describe them and have the framework generate them.  Include as much or as little detail as is needed.
  • Generate your documentation with every build - use strong types within the documentation so your build will break if it isn't up to date which means your documentation is never obsolete.
  • Incorporate your C# comments at will.
  • Allow for blocks of text - they can accompany diagrams to provide in-depth descriptions.
  • Tweak your framework to completely change the look and style of your generated documentation in one fell swoop.