We are trying to define a Service Fabric Stateless Service which listeners for UDP data.
We are working with Microsoft who have said that it IS supported and that I should set up for TCP; below is the snippet from the ServiceManifest.xml file :
<Resources>
<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" Protocol="tcp" Port="12345" Type="Input" />
</Endpoints>
</Resources>
The service starts fine but I cannot make the service receive any UDP data and if I do a netstat -a
I cannot see anything listening on the port in either TCP or UDP.
I've done plenty of research on online and I've not found much on creating custom ICommunicationListener but I'm hoping that someone else might be able to verify if this should be possible with SF.
Here is the ICommunicationListener implementation:
public UdpCommunicationListener(string serviceEndPoint,
ServiceInitializationParameters serviceInitializationParameters, Action<UdpReceiveResult> connector)
{
if (serviceInitializationParameters == null)
{
throw new ArgumentNullException(nameof(serviceInitializationParameters));
}
var endPoint = serviceInitializationParameters
.CodePackageActivationContext
.GetEndpoint(serviceEndPoint ?? "ServiceEndPoint");
_connector = connector;
_ipAddress = FabricRuntime.GetNodeContext().IPAddressOrFQDN;
_port = endPoint.Port;
_server = new UdpServer(_ipAddress, _port);
_server.Open();
}
public Task<string> OpenAsync(CancellationToken cancellationToken)
{
_listener = _server.Listen(_connector);
return Task.FromResult($"udp::{_ipAddress}:{_port}");
}
public Task CloseAsync(CancellationToken cancellationToken)
{
this.Abort();
return Task.FromResult(true);
}
public void Abort()
{
_listener.Dispose();
_server?.Close();
}
}
public class UdpServer
{
private readonly UdpClient _udpClient;
private IObservable<UdpReceiveResult> _receiveStream;
public UdpServer(string ipAddress, int port)
{
Id = Guid.NewGuid();
_udpClient = new UdpClient(ipAddress, port);
}
public Guid Id { get; }
public void Open()
{
_receiveStream = _udpClient.ReceiveStream().Publish().RefCount();
}
public void Close()
{
//TODO: Not sure how to stop the process
}
public IDisposable Listen(Action<UdpReceiveResult> process)
{
return _receiveStream.Subscribe(async r =>
{
process(r);
});
}
}