I have a requirement to set up a Stateful Service Fabric app that listens for TCP requests and then pops the messages on to a Reliable Queue.
There's plenty of examples around for HTTP and WCF endpoints, but i can find nothing for simple TCP.
In my ServiceManifest.xml
I have this
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="ServiceEndpoint" />
<!-- This endpoint is used by the replicator for replicating the state of your service.
This endpoint is configured through a ReplicatorSettings config section in the Settings.xml
file under the ConfigPackage. -->
<Endpoint Name="ReplicatorEndpoint" />
<Endpoint Name="tcpEndpoint" Protocol="tcp" Port="10100"/>
</Endpoints>
I have a listener that implements ICommunicationListener
called TcpCommunicationListener
public class TcpCommunicationListener : ICommunicationListener
{
private readonly ServiceEventSource eventSource;
private readonly ServiceContext serviceContext;
private readonly string endpointName;
private string listeningAddress;
private string hostAddress;
public TcpCommunicationListener(ServiceContext serviceContext, ServiceEventSource eventSource, string endpointName)
{
if (serviceContext == null)
{
throw new ArgumentNullException(nameof(serviceContext));
}
if (endpointName == null)
{
throw new ArgumentNullException(nameof(endpointName));
}
if (eventSource == null)
{
throw new ArgumentNullException(nameof(eventSource));
}
this.serviceContext = serviceContext;
this.endpointName = endpointName;
this.eventSource = eventSource;
}
public Task<string> OpenAsync(CancellationToken cancellationToken)
{
var serviceEndpoint = this.serviceContext.CodePackageActivationContext.GetEndpoint(this.endpointName);
var protocol = serviceEndpoint.Protocol;
int port = serviceEndpoint.Port;
//StatefulServiceContext statefulServiceContext = this.serviceContext as StatefulServiceContext;
this.hostAddress = FabricRuntime.GetNodeContext().IPAddressOrFQDN;
this.listeningAddress = string.Format(
CultureInfo.InvariantCulture,
"{0}://{1}:{2}",
protocol,
hostAddress,
port
);
try
{
this.eventSource.Message("Starting tcp listener " + this.listeningAddress);
return Task.FromResult(this.hostAddress);
}
catch (Exception ex)
{
this.eventSource.Message("Tcp Listener failed to open endpoint {0}. {1}", this.endpointName, ex.ToString());
throw;
}
}
public Task CloseAsync(CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public void Abort()
{
throw new NotImplementedException();
}
}
I also have a StatefulService
called ListenerService
internal sealed class ListenerService : StatefulService
{
public ListenerService(StatefulServiceContext context)
: base(context)
{
}
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
var endpoints = Context.CodePackageActivationContext.GetEndpoints()
.Where(endpoint => endpoint.Protocol == EndpointProtocol.Tcp)
.Select(endpoint => endpoint.Name);
return endpoints.Select(endpoint => new ServiceReplicaListener(
serviceContext => new TcpCommunicationListener(serviceContext, ServiceEventSource.Current, endpoint), endpoint));
}
protected override async Task RunAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
//do i spin up a TcpListener here?
}
}
So my question is how do I get the messages that are being received?
Do I have to create a TcpListener
in the RunAsync
method of my ListenerService
? If that's the case then what's the point of specifying an endpoint in the ServiceManifest.xml
?
OR
Do I need to do something in the OpenAsync
method of the TcpCommunicationListener?
Right now your communication listener code only publishes a Uri when OpenAsync
is called. You'll also need to actually start listening on that endpoint. So for instance, you could open a Socket at that time.
You can also use WCF with a NetTcpBinding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With