To permit communication, we need to define a contract between the two processes. All I'd like this contract (let's call it HealthCheck) to define is an operation GetTimestamp. Given that my two separate processes will be two separate projects in Visual Studio, and that they both need to access this contract, we'll create a third class library called SharedTypes that will contain nothing but the contract.
SharedTypes (contains the contract)
Assembly references: System.ServiceModel
We'll define the contract as an interface, decorated by System.ServiceModel.ServiceContract. The interface's one method signature (GetTimestamp) should be decorated by System.ServiceModel.OperationContract.
using System;
using System.ServiceModel;
namespace SharedTypes
{
[ServiceContract]
public interface IHealthCheck
{
[OperationContract]
DateTime GetTimestamp();
}
}
Server
Assembly references: SharedTypes, System.ServiceModel
The server process, perhaps unsurprisingly, will need to implement this contract interface as follows:
using System;
using SharedTypes;
namespace Server
{
class HealthCheck : IHealthCheck
{
public DateTime GetTimestamp()
{
return DateTime.Now;
}
}
}
The program's main method will simply instantiate and open a ServiceHost to expose the service, and hang around in the background:
using System;
using System.ServiceModel;
namespace Server
{
class Program
{
static void Main(string[] args)
{
ServiceHost serviceHost = new ServiceHost(typeof(HealthCheck));
serviceHost.Open();
// Keep the process running (hence the service open) for an hour
System.Threading.Thread.Sleep(3600000);
}
}
}
Finally, we'll need to specify the address and protocol by which the service can be called. Part of the joy of WCF is allowing this to be configurable by an end-user or sysadmin, so we'll specify a minimal app.config to contain the core settings we require:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Server.HealthCheck">
<endpoint address="basic" binding="basicHttpBinding"
contract="SharedTypes.IHealthCheck" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/HealthCheck" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
Client
Assembly references: SharedTypes, System.ServiceModel
The client will also need to have a class that implements the service contract, but we'll make it such that calls to its methods actually result in a remote call over WCF:
using System;
using System.ServiceModel;
using SharedTypes;
namespace Client
{
public class HealthCheck : ClientBase<IHealthCheck>, IHealthCheck
{
public DateTime GetTimestamp()
{
return base.Channel.GetTimestamp();
}
}
}
The program's main method will just sit in a loop calling and echoing the result from GetTimestamp:
using System;
namespace Client
{
class Program
{
static void Main(string[] args)
{
HealthCheck healthCheck = new HealthCheck();
while (true)
{
Console.WriteLine(healthCheck.GetTimestamp());
// Wait for a second
System.Threading.Thread.Sleep(1000);
}
}
}
}
Again, we'll need to specify in app.config the location of the server, and the protocol we want to use:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:8080/HealthCheck/basic"
binding="basicHttpBinding"
contract="SharedTypes.IHealthCheck" />
</client>
</system.serviceModel>
</configuration>
No comments:
Post a Comment