在开始介绍ZeroMQ之前,先看下前端界面的,主要完善了策略的编辑功能,具体代码大家可以看Github上面的项目源码,如有疑问请入QQ群21323365,或直接留言。
由于下面章节会涉及到程序间通讯,会用到ZeroMQ通讯中间件,所以先介绍下ZeroMQ的几种通讯模式,并且通过几个小Demo来初步了解它的应用。
发布和订阅模式,该模式主要用于行情中心在收到交易所行情并封装好消息后通过PUB方式发布给客户端,客户端通过SUB方式订阅需要接收行情的合约。
推拉模式,该模式主要用于后端测试工人在测试完成后将结果推送给回测中心,由回测中心统一将测试报告入库。
路由模式,该模式主要将客户端指令转发给下单工人,由下单工人加指令发送至交易所场内。
public class ZMQTest
{
bool isClosing = false;
///
/// 启动发布服务器
///
public void StartPubServer()
{
Task task = new Task(() =>
{
// 创建发布服务的Socket
using (var server = new ZeroMQ.ZSocket(ZeroMQ.ZSocketType.PUB))
{
server.Bind("tcp://127.0.0.1:1001");
while (true)
{
if (isClosing)
{
using (var quit = new ZeroMQ.ZFrame("Quit"))
{
server.SendFrame(quit);
}
break;
}
using (var head = new ZeroMQ.ZFrame("Time"))
{
server.SendFrameMore(head);
}
using (var body = new ZeroMQ.ZFrame(DateTime.Now.TimeOfDay.ToString()))
{
server.SendFrame(body);
}
Thread.Sleep(2000);
}
Console.WriteLine("PubServer is Closed.");
}
});
task.Start();
}
///
/// 启动订阅客户端
///
public void StartSubClient()
{
Task task = new Task(() =>
{
// 创建发布服务的Socket
using (var client = new ZeroMQ.ZSocket(ZeroMQ.ZSocketType.SUB))
{
client.Connect("tcp://127.0.0.1:1001");
client.Subscribe("Quit");
client.Subscribe("Time"); // 订阅内容标识
while (true)
{
if (isClosing)
{
break;
}
using (var msg = client.ReceiveMessage())
{
if (msg.Count == 1)
{
break;
}
if (msg.Count == 2)
{
var title = msg[0].ReadString(); // ReadString只能调用一次,多次调用会取不到数据
var content = msg[1].ReadString(); // 如需多次使用该消息,像这样存放到临时变量中
Console.WriteLine("{0}->{1}", title, content);
}
}
}
Console.WriteLine("SubClient is Closed.");
}
});
task.Start();
}
///
/// 启动消息拉取服务器
///
public void StartPullServer()
{
Task task = new Task(() =>
{
// 创建发布服务的Socket
using (var server = new ZeroMQ.ZSocket(ZeroMQ.ZSocketType.PULL))
{
server.Bind("tcp://127.0.0.1:1002");
while (true)
{
if (isClosing)
{
break;
}
using (var msg = server.ReceiveMessage())
{
var content = msg[0].ReadString();
if (content == "Quit")
{
break;
}
else
{
Console.WriteLine("{0}", content);
}
}
}
Console.WriteLine("PullServer is Closed.");
}
});
task.Start();
}
///
/// 启动消息推送客户端
///
public void StartPushClient()
{
Task task = new Task(() =>
{
// 创建推送消息的Socket
using (var client = new ZeroMQ.ZSocket(ZeroMQ.ZSocketType.PUSH))
{
client.Connect("tcp://127.0.0.1:1002");
while (true)
{
if (isClosing)
{
using (var content = new ZeroMQ.ZFrame("Quit"))
{
client.SendFrame(content);
}
break;
}
using (var content = new ZeroMQ.ZFrame("Push->"+DateTime.Now.TimeOfDay.ToString()))
{
client.SendFrame(content);
}
Thread.Sleep(2000);
}
Console.WriteLine("PushClient is Closed.");
}
});
task.Start();
}
///
/// 启动路由服务器
///
public void StartRouterServer()
{
var front = new ZeroMQ.ZSocket(ZeroMQ.ZSocketType.ROUTER);
var backend = new ZeroMQ.ZSocket(ZeroMQ.ZSocketType.ROUTER);
Task taskFront = new Task(() =>
{
int i = 0;
front.Bind("tcp://127.0.0.1:1003");
while (true)
{
if (isClosing)
{
break;
}
using (var msg = front.ReceiveMessage())
{
var id = msg[0].ReadString();
Console.WriteLine("Received From Client:{0}", id);
var content = "Do Work->" + msg[1].ReadString();
var replyMsg = "No Worker";
if (workerList.Count > 0)
{
if (i > workerList.Count - 1)// 负载均衡工人
{
i = 0;
}
using (var head = new ZeroMQ.ZFrame(workerList[i]))
{
backend.SendFrameMore(head);
}
using (var body = new ZeroMQ.ZFrame(content))
{
backend.SendFrame(body);
}
replyMsg = "Beging Working...";
i++;
}
using (var reply = new ZeroMQ.ZFrame(replyMsg))
{
front.SendFrame(reply);
}
}
}
front.Close();
Console.WriteLine("FrontServer is Closed.");
});
Task taskBacend = new Task(() =>
{
backend.Bind("tcp://127.0.0.1:1004");
while (true)
{
if (isClosing)
{
break;
}
// 接收工人上线消息
using (var msg = backend.ReceiveMessage())
{
var worker = msg[0].ReadString();
var info = msg[1].ReadString();
if (info == "Quit")
{
workerList.Remove(worker);
}
if (!workerList.Contains(worker))
{
workerList.Add(worker);
}
Console.WriteLine("{0} is standby, Msg:{1}", worker, info);
}
}
backend.Close();
Console.WriteLine("BackendServer is Closed.");
});
taskFront.Start();
taskBacend.Start();
}
List workerList = new List();
///
/// 启动订阅客户端
///
public void StartDealerClient()
{
Task task = new Task(() =>
{
// 创建推送消息的Socket
using (var client = new ZeroMQ.ZSocket(ZeroMQ.ZSocketType.DEALER))
{
client.Identity = Encoding.UTF8.GetBytes("Client1");
client.Connect("tcp://127.0.0.1:1003");
while (true)
{
if (isClosing)
{
using (var content = new ZeroMQ.ZFrame("Quit"))
{
client.SendFrame(content);
}
break;
}
using (var content = new ZeroMQ.ZFrame("Task " + DateTime.Now.TimeOfDay.ToString()))
{
client.SendFrame(content);
}
Thread.Sleep(10000);
}
Console.WriteLine("DealerClient is Closed.");
}
});
task.Start();
}
///
/// 启动订阅客户端
///
public void StartDealerWorker(string id)
{
Task task = new Task(() =>
{
using (var worker = new ZeroMQ.ZSocket(ZeroMQ.ZSocketType.DEALER))
{
worker.Identity = Encoding.UTF8.GetBytes(id);
worker.Connect("tcp://127.0.0.1:1004");
using (var content = new ZeroMQ.ZFrame("hello"))
{
worker.SendFrame(content);
}
while (true)
{
if (isClosing)
{
using (var quit = new ZeroMQ.ZFrame("Quit"))
{
worker.SendFrame(quit);
}
break;
}
using (var msg = worker.ReceiveMessage())
{
var content = msg[0].ReadString();
Console.WriteLine("Begin Working->" + content);
using (var info = new ZeroMQ.ZFrame("i am working..."))
{
worker.SendFrame(info);
}
}
}
Console.WriteLine("BackendClient is Closed.");
}
});
task.Start();
}
public void Stop()
{
isClosing = true;
}
}