-
Notifications
You must be signed in to change notification settings - Fork 0
/
FtdcMdApiImpl.h
282 lines (236 loc) · 7.51 KB
/
FtdcMdApiImpl.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#if !defined(_FTDCMDAPIIMPL_H)
#define _FTDCMDAPIIMPL_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <boost/asio.hpp>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <vector>
#include <string>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/strand.hpp>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/program_options.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/typeof/typeof.hpp>
#include <fstream>
#include <limits>
#include <boost/thread.hpp>
#include "ThostFtdcMdApi.h"
namespace beast = boost::beast; // from <boost/beast.hpp>
namespace http = beast::http; // from <boost/beast/http.hpp>
namespace net = boost::asio; // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
// Report a failure
void
fail(beast::error_code ec, char const* what)
{
//std::cerr << what << ": " << ec.message() << "\n";
}
///API接口实现
class CFtdcMdApiImpl : public CThostFtdcMdApi
{
public:
///构造函数
CFtdcMdApiImpl();
void OnSnapTime(const boost::system::error_code& error);
void HandleMarketData(std::vector<std::string>& data);
std::string url_;
std::string port_;
net::io_context ioc_;
tcp::resolver resolver_;
beast::tcp_stream stream_;
beast::flat_buffer buffer_; // (Must persist between reads)
http::request<http::empty_body> req_;
http::response<http::string_body> res_;
std::map<std::string, size_t> _mInstruments;
boost::thread* _pthread;
// Start the asynchronous operation
void
query(char const* target)
{
// Set up an HTTP GET request message
req_.version(11);
req_.method(http::verb::get);
req_.target(target);
req_.set(http::field::host, url_);
req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
// Look up the domain name
resolver_.async_resolve(
url_,
port_,
beast::bind_front_handler(
&CFtdcMdApiImpl::on_resolve,
this));
}
void
on_resolve(
beast::error_code ec,
tcp::resolver::results_type results)
{
if (ec) {
// Look up the domain name
resolver_.async_resolve(
url_, port_,
beast::bind_front_handler(
&CFtdcMdApiImpl::on_resolve,
this));
return;
}
// Set a timeout on the operation
stream_.expires_after(std::chrono::seconds(30));
// Make the connection on the IP address we get from a lookup
stream_.async_connect(
results,
beast::bind_front_handler(
&CFtdcMdApiImpl::on_connect,
this));
}
void
on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
{
if (ec) {
// Look up the domain name
resolver_.async_resolve(
url_, port_,
beast::bind_front_handler(
&CFtdcMdApiImpl::on_resolve,
this));
return;
}
res_.body().clear();
// Set a timeout on the operation
stream_.expires_after(std::chrono::seconds(30));
// Send the HTTP request to the remote host
http::async_write(stream_, req_,
beast::bind_front_handler(
&CFtdcMdApiImpl::on_write,
this));
}
void
on_write(
beast::error_code ec,
std::size_t bytes_transferred)
{
boost::ignore_unused(bytes_transferred);
if (ec)
return fail(ec, "write");
// Receive the HTTP response
http::async_read(stream_, buffer_, res_,
beast::bind_front_handler(
&CFtdcMdApiImpl::on_read,
this));
}
void
on_read(
beast::error_code ec,
std::size_t bytes_transferred)
{
boost::ignore_unused(bytes_transferred);
if (ec) {
//if (m_pSpi)
// m_pSpi->OnFrontDisconnected(0);
return fail(ec, "read");
}
// Write the message to standard out
//std::cout << res_ << std::endl;
std::vector<std::string> vTemp, vPrices;
std::string pkg = res_.body();
boost::split(vTemp, pkg, boost::is_any_of("\""));
for (size_t i = 0; i + 1 < vTemp.size(); i += 2) {
vPrices.push_back(vTemp[i + 1]);
}
HandleMarketData(vPrices);
// 使用短连接机制,接收完成后关闭连接
// Gracefully close the socket
stream_.socket().shutdown(tcp::socket::shutdown_both, ec);
// not_connected happens sometimes so don't bother reporting it.
if(ec && ec != beast::errc::not_connected)
return fail(ec, "shutdown");
// If we get here then the connection is closed gracefully
}
///获取API的版本信息
///@retrun 获取到的版本号
//const char *GetApiVersion(){return 0;};
///删除接口对象本身
///@remark 不再使用本接口对象时,调用该函数删除接口对象
virtual void Release();
///初始化
///@remark 初始化运行环境,只有调用后,接口才开始工作
virtual void Init();
///等待接口线程结束运行
///@return 线程退出代码
virtual int Join();
///获取当前交易日
///@retrun 获取到的交易日
///@remark 只有登录成功后,才能得到正确的交易日
virtual const char *GetTradingDay();
///注册前置机网络地址
///@param pszFrontAddress:前置机网络地址。
///@remark 网络地址的格式为:“protocol://ipaddress:port”,如:”tcp://127.0.0.1:17001”。
///@remark “tcp”代表传输协议,“127.0.0.1”代表服务器地址。”17001”代表服务器端口号。
virtual void RegisterFront(char *pszFrontAddress);
///注册名字服务器网络地址
///@param pszNsAddress:名字服务器网络地址。
///@remark 网络地址的格式为:“protocol://ipaddress:port”,如:”tcp://127.0.0.1:12001”。
///@remark “tcp”代表传输协议,“127.0.0.1”代表服务器地址。”12001”代表服务器端口号。
///@remark RegisterFront优先于RegisterNameServer
virtual void RegisterNameServer(char *pszNsAddress);
///注册回调接口
///@param pSpi 派生自回调接口类的实例
virtual void RegisterSpi(CThostFtdcMdSpi *pSpi);
///用户登录请求
virtual int ReqUserLogin(CThostFtdcReqUserLoginField *pReqUserLogin, int nRequestID);
///用户退出请求
virtual int ReqUserLogout(CThostFtdcUserLogoutField *pUserLogout, int nRequestID);
///订阅行情。
///@param ppInstrumentID 合约ID
///@param nCount 要订阅/退订行情的合约个数
///@remark
virtual int SubscribeMarketData(char* ppInstrumentID[], int nCount);
///退订行情。
///@param ppInstrumentID 合约ID
///@param nCount 要订阅/退订行情的合约个数
///@remark
virtual int UnSubscribeMarketData(char* ppInstrumentID[], int nCount);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///暂时不实现的接口
///注册名字服务器用户信息
///@param pFensUserInfo:用户信息。
virtual void RegisterFensUserInfo(CThostFtdcFensUserInfoField * pFensUserInfo){return;};
///订阅询价。
///@param ppInstrumentID 合约ID
///@param nCount 要订阅/退订行情的合约个数
///@remark
virtual int SubscribeForQuoteRsp(char* ppInstrumentID[], int nCount) { return -3; }
///退订询价。
///@param ppInstrumentID 合约ID
///@param nCount 要订阅/退订行情的合约个数
///@remark
virtual int UnSubscribeForQuoteRsp(char* ppInstrumentID[], int nCount) { return -3; }
#if defined(V6_3_19) || defined(V6_5_1) || defined(V6_6_1_P1) || defined(V6_6_7) || defined(V6_6_9) || defined(V6_7_0) || defined(V6_7_1) || defined(V6_7_2) || defined(V6_7_7)
///请求查询组播合约
virtual int ReqQryMulticastInstrument(CThostFtdcQryMulticastInstrumentField *pQryMulticastInstrument, int nRequestID) { return -3; }
#endif
public:
CThostFtdcMdSpi *m_pSpi;
CThostFtdcRspUserLoginField ThostRspUserLogin;
CThostFtdcUserLogoutField ThostUserLogout;
CThostFtdcRspInfoField ThostRspInfo;
TThostFtdcDateType TradingDay;
boost::asio::deadline_timer m_snap_timer;
};
#endif