服务端:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using NetMQ;
using NetMQ.Sockets;
namespace Freelance.ModelOne.Server
{
internal static class Program
{
private const uint PortNumber = 5555;
private static void Main()
{
using (var response = new ResponseSocket())
{
string address = GetComputerLanIP();
if (!string.IsNullOrEmpty(address))
{
Console.WriteLine("Binding tcp://{0}:{1}", address, PortNumber);
response.Bind($"tcp://{address}:{PortNumber}");
while (true)
{
bool hasMore;
string msg = response.ReceiveFrameString(out hasMore);
if (string.IsNullOrEmpty(msg))
{
Console.WriteLine("No msg received.");
break;
}
Console.WriteLine("Msg received! {0}", msg);
response.SendFrame(msg, hasMore);
Thread.Sleep(1000);
}
response.Options.Linger = TimeSpan.Zero;
}
else
{
Console.WriteLine("Wrong IP address");
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
private static string GetComputerLanIP()
{
string strHostName = Dns.GetHostName();
IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
foreach (var ipAddress in ipEntry.AddressList)
{
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
return ipAddress.ToString();
}
}
return "";
}
}
}
接收端:
using System;
using System.Collections.Generic;
using NetMQ;
using NetMQ.Sockets;
namespace Freelance.ModelOne.Client
{
internal static class Program
{
private const int RequestTimeout = 1000; // ms
private const int MaxRetries = 50; // Before we abandon
private static void Main()
{
var endpoints = new List<string>
{
"tcp://192.168.56.1:5555",
//"tcp://*** Add your first endpoint ***",
//"tcp://*** Add your second endpoint ***"
};
if (endpoints.Count == 1)
{
for (int i = 0; i < MaxRetries; i++)
{
if (TryRequest(endpoints[0], $"Hello from endpoint {endpoints[0]}"))
break;
}
}
else if (endpoints.Count > 1)
{
foreach (string endpoint in endpoints)
{
if (TryRequest(endpoint, $"Hello from endpoint {endpoint}"))
break;
}
}
else
{
Console.WriteLine("No endpoints");
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
private static bool TryRequest(string endpoint, string requestString)
{
Console.WriteLine("Trying echo service at {0}", endpoint);
using (var client = new RequestSocket())
{
client.Options.Linger = TimeSpan.Zero;
client.Connect(endpoint);
client.SendFrame(requestString);
client.ReceiveReady += ClientOnReceiveReady;
bool pollResult = client.Poll(TimeSpan.FromMilliseconds(RequestTimeout));
client.ReceiveReady -= ClientOnReceiveReady;
client.Disconnect(endpoint);
return pollResult;
}
}
private static void ClientOnReceiveReady(object sender, NetMQSocketEventArgs args)
{
Console.WriteLine("Server replied ({0})", args.Socket.ReceiveFrameString());
}
}
}
运行结果:
结论:
1、还是请求回应模型。
2、解决了服务端和发送端都阻塞的问题,即引入了第一篇中的Timeout效果。
3、结构中只存在一个服务端,如客户端尝试重连崩溃的服务端则会永远尝试连接而无法得知服务端状态。