AMPSharp - An AMP library for Mono and Microsoft .NET¶
- 100% managed C# code
- Client and Server
- Extensive unit-test coverage
- Runs with Microsoft .NET or Mono
- Blocking and Non-Blocking (asynchronous) interfaces
- Full set of AMP data types
- Packaged in Debian unstable as of September, 2011
- Packaged via NuGet
Code and downloads are hosted on Launchpad:¶
Examples¶
Server for a Sum
and Divide
command:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace MathServer
{
class Server
{
static void Main(string[] args)
{
int port = 1234;
var listener = new TcpListener(port);
listener.Start(5);
Console.WriteLine("Listening on port {0}", port);
TcpClient client;
AMP.Protocol protocol;
// the AMP.Command's we're going to respond to
var sum = new Sum();
var div = new Divide();
while (true)
{
client = listener.AcceptTcpClient();
protocol = new AMP.Protocol(client.GetStream());
// we could also pass a 'state' argument to RegisterResponder
// which becomes the 'state' argument in the responders (below).
// Since we aren't passing anything, then state will always be null
protocol.RegisterResponder(sum, handleSum);
protocol.RegisterResponder(div, handleDivide);
protocol.StartReading(); // start the async data-reading loop
}
}
static Object handleSum(AMP.Msg reqMsg, Object state)
{
int a = (int)reqMsg["a"];
int b = (int)reqMsg["b"];
int total = a + b;
Console.WriteLine("Did a sum: {0} + {1} = {2}", a, b, total);
return new AMP.Msg {{"total", total}};
}
static Object handleDivide(AMP.Msg reqMsg, Object state)
{
int numerator = (int)reqMsg["numerator"];
int denominator = (int)reqMsg["denominator"];
decimal result = (decimal)numerator / denominator;
Console.WriteLine("Did a division: {0} / {1} = {2}", numerator, denominator, result);
return new AMP.Msg { { "result", result } };
}
}
public class Sum: AMP.Command
{
public Sum()
: base("Sum")
{
AMP.IAmpType int32 = new AMP.Type.Int32();
AddArgument("a", int32);
AddArgument("b", int32);
AddResponse("total", int32);
}
}
public class Divide : AMP.Command
{
public Divide()
: base("Divide")
{
AMP.IAmpType int32 = new AMP.Type.Int32();
AMP.IAmpType dec = new AMP.Type.Decimal();
AddArgument("numerator", int32);
AddArgument("denominator", int32);
AddResponse("result", dec);
AddError(typeof(DivideByZeroException), Encoding.UTF8.GetBytes("ZERO_DIVISION"));
}
}
}
Client code that excersies Sum
and Divide
commands in various ways:
using System;
using System.Net.Sockets;
using System.Threading;
namespace MathClient
{
class Client
{
static void Main(string[] args)
{
string hostname = "localhost";
int port = 1234;
var client = new TcpClient(hostname, port);
var protocol = new AMP.Protocol(client.GetStream());
protocol.StartReading(); // start the async data-reading loop
// Instantiate the Commands we're going to call
AMP.Command sum = new MathServer.Sum();
AMP.Command div = new MathServer.Divide();
// Make one remote call synchronously. CallRemote() will raise an exception if
// anything goes wrong making the call.
AMP.Msg msg = protocol.CallRemote(sum, new AMP.Msg { { "a", 5 }, { "b", 7 } });
Console.WriteLine("Got sum result: {0}", (int)msg["total"]);
Thread.Sleep(2000);
// Now make some asynchronous calls in a loop
int count = 3;
while (count-- > 0)
{
// pass the AMP.Protocol object though as the `state' parameter since we need it in the callback
protocol.BeginCallRemote(sum, new AMP.Msg { { "a", 13 }, { "b", 81 } }, CBGotSumResponse, protocol);
Thread.Sleep(2000);
}
// Do a division
try
{
msg = protocol.CallRemote(div, new AMP.Msg { { "numerator", 10 }, { "denominator", 3 } });
}
catch (DivideByZeroException)
{
System.Console.WriteLine("Shouldn't have caused zero division here!");
return;
}
Console.WriteLine("Got division result: {0}", (decimal)msg["result"]);
// Now do it again, but this time cause a DivideByZeroException on the remote end,
// which will result in a DivideByZeroException being raised here, because the
// Divide command has been implemented to handle this particular Exception.
try
{
msg = protocol.CallRemote(div, new AMP.Msg { { "numerator", 10 }, { "denominator", 0 } });
}
catch (DivideByZeroException)
{
System.Console.WriteLine("Got DivideByZeroException as expected.");
}
Console.ReadKey(); // Press any key to continue...
}
// Call-back method for receiving result from server asynchronously
static void CBGotSumResponse(IAsyncResult ar)
{
var protocol = (AMP.Protocol)ar.AsyncState;
// EndCallRemote() will raise if any error occured during the remote call
AMP.Msg respMsg = protocol.EndCallRemote(ar);
Console.WriteLine("Got sum: {0}", (int)respMsg["total"]);
}
}
}