期貨量化軟件:赫茲量化軟件 的 WebSocket — 使用 Windows API
我們討論了 WebSocket 協(xié)議的基礎(chǔ)知識,并創(chuàng)建了一個(gè)依賴 MQL5 實(shí)現(xiàn)的套接字客戶端。 這一次,我們將利用 Windows API 為 赫茲量化 程序構(gòu)建 WebSocket 客戶端。 它也許是次一級的最佳選項(xiàng),因?yàn)檫@不需要額外的軟件,一切均由操作系統(tǒng)提供。 我們將把客戶端作為一個(gè)類來實(shí)現(xiàn),并借助 Binary.com WebSocket API 將實(shí)時(shí)的即時(shí)報(bào)價(jià)數(shù)據(jù)投喂給 赫茲量化。
Windows 中的 WebSocket
當(dāng)來到 Windows API 和 Internet,MQL5 開發(fā)人員最熟悉 Windows Internet(WinINeT)函數(shù)庫。 它實(shí)現(xiàn)了諸如文件傳輸協(xié)議(FTP)和 HTTP 等眾多互聯(lián)網(wǎng)協(xié)議。 與之類似的是 Windows HTTP 服務(wù)(WinHTTP)函數(shù)庫。 它是 HTTP 協(xié)議的專用庫,擁有服務(wù)器端開發(fā)的有用功能。 WinHTTP 公開的一些功能是處理 WebSocket 連接的實(shí)用程序。
我們將為 赫茲量化 創(chuàng)建的客戶端以同步模式操作。 這意味著函數(shù)調(diào)用將阻塞執(zhí)行,直到它們返回響應(yīng)。 例如,調(diào)用 WinHttpWebSocketReceive() 將阻塞正在執(zhí)行的線程,直到有數(shù)據(jù)可供讀取。 在創(chuàng)建 赫茲量化 應(yīng)用程序時(shí)請記住這一點(diǎn)。
winhttp 函數(shù)是在包含文件 winhttp.mqh 中聲明和導(dǎo)入。
#include <WinAPI\errhandlingapi.mqh> #define WORD ?ushort #define DWORD ulong #define BYTE ?uchar #define INTERNET_PORT WORD #define HINTERNET long #define LPVOID uint& #define WINHTTP_ERROR_BASE ? ? ? ? ? ? ? ? ? ? 12000 #define ERROR_WINHTTP_OUT_OF_HANDLES ? ? ? ? ? (WINHTTP_ERROR_BASE + 1) #define ERROR_WINHTTP_TIMEOUT ? ? ? ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 2) #define ERROR_WINHTTP_INTERNAL_ERROR ? ? ? ? ? (WINHTTP_ERROR_BASE + 4) #define ERROR_WINHTTP_INVALID_URL ? ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 5) #define ERROR_WINHTTP_UNRECOGNIZED_SCHEME ? ? ?(WINHTTP_ERROR_BASE + 6) #define ERROR_WINHTTP_NAME_NOT_RESOLVED ? ? ? ?(WINHTTP_ERROR_BASE + 7) #define ERROR_WINHTTP_INVALID_OPTION ? ? ? ? ? (WINHTTP_ERROR_BASE + 9) #define ERROR_WINHTTP_OPTION_NOT_SETTABLE ? ? ?(WINHTTP_ERROR_BASE + 11) #define ERROR_WINHTTP_SHUTDOWN ? ? ? ? ? ? ? ? (WINHTTP_ERROR_BASE + 12) #define ERROR_WINHTTP_LOGIN_FAILURE ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 15) #define ERROR_WINHTTP_OPERATION_CANCELLED ? ? ?(WINHTTP_ERROR_BASE + 17) #define ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ? ?(WINHTTP_ERROR_BASE + 18) #define ERROR_WINHTTP_INCORRECT_HANDLE_STATE ? (WINHTTP_ERROR_BASE + 19) #define ERROR_WINHTTP_CANNOT_CONNECT ? ? ? ? ? (WINHTTP_ERROR_BASE + 29) #define ERROR_WINHTTP_CONNECTION_ERROR ? ? ? ? (WINHTTP_ERROR_BASE + 30) #define ERROR_WINHTTP_RESEND_REQUEST ? ? ? ? ? (WINHTTP_ERROR_BASE + 32) #define ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED ?(WINHTTP_ERROR_BASE + 44) #define ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ? (WINHTTP_ERROR_BASE + 100) #define ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ? (WINHTTP_ERROR_BASE + 101) #define ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND (WINHTTP_ERROR_BASE + 102) #define ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN (WINHTTP_ERROR_BASE + 103) #define ERROR_WINHTTP_HEADER_NOT_FOUND ? ? ? ? ? ? (WINHTTP_ERROR_BASE + 150) #define ERROR_WINHTTP_INVALID_SERVER_RESPONSE ? ? ?(WINHTTP_ERROR_BASE + 152) #define ERROR_WINHTTP_INVALID_HEADER ? ? ? ? ? ? ? (WINHTTP_ERROR_BASE + 153) #define ERROR_WINHTTP_INVALID_QUERY_REQUEST ? ? ? ?(WINHTTP_ERROR_BASE + 154) #define ERROR_WINHTTP_HEADER_ALREADY_EXISTS ? ? ? ?(WINHTTP_ERROR_BASE + 155) #define ERROR_WINHTTP_REDIRECT_FAILED ? ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 156) #define ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR ?(WINHTTP_ERROR_BASE + 178) #define ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT ? ? (WINHTTP_ERROR_BASE + 166) #define ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT (WINHTTP_ERROR_BASE + 167) #define ERROR_WINHTTP_UNHANDLED_SCRIPT_TYPE ? ? (WINHTTP_ERROR_BASE + 176) #define ERROR_WINHTTP_SCRIPT_EXECUTION_ERROR ? ?(WINHTTP_ERROR_BASE + 177) #define ERROR_WINHTTP_NOT_INITIALIZED ? ? ? ? ?(WINHTTP_ERROR_BASE + 172) #define ERROR_WINHTTP_SECURE_FAILURE ? ? ? ? ? (WINHTTP_ERROR_BASE + 175) #define ERROR_WINHTTP_SECURE_CERT_DATE_INVALID ? ?(WINHTTP_ERROR_BASE + 37) #define ERROR_WINHTTP_SECURE_CERT_CN_INVALID ? ? ?(WINHTTP_ERROR_BASE + 38) #define ERROR_WINHTTP_SECURE_INVALID_CA ? ? ? ? ? (WINHTTP_ERROR_BASE + 45) #define ERROR_WINHTTP_SECURE_CERT_REV_FAILED ? ? ?(WINHTTP_ERROR_BASE + 57) #define ERROR_WINHTTP_SECURE_CHANNEL_ERROR ? ? ? ?(WINHTTP_ERROR_BASE + 157) #define ERROR_WINHTTP_SECURE_INVALID_CERT ? ? ? ? (WINHTTP_ERROR_BASE + 169) #define ERROR_WINHTTP_SECURE_CERT_REVOKED ? ? ? ? (WINHTTP_ERROR_BASE + 170) #define ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE ? ? (WINHTTP_ERROR_BASE + 179) #define ERROR_WINHTTP_AUTODETECTION_FAILED ? ? ? ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 180) #define ERROR_WINHTTP_HEADER_COUNT_EXCEEDED ? ? ? ? ? ? ? ? (WINHTTP_ERROR_BASE + 181) #define ERROR_WINHTTP_HEADER_SIZE_OVERFLOW ? ? ? ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 182) #define ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW (WINHTTP_ERROR_BASE + 183) #define ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW ? ? ? ? ? ? ? (WINHTTP_ERROR_BASE + 184) #define ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 185) #define ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY ? ? (WINHTTP_ERROR_BASE + 186) #define ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED_PROXY ? ? ? ? (WINHTTP_ERROR_BASE + 187) #define ERROR_WINHTTP_SECURE_FAILURE_PROXY ? ? ? ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 188) #define ERROR_WINHTTP_RESERVED_189 ? ? ? ? ? ? ? ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 189) #define ERROR_WINHTTP_HTTP_PROTOCOL_MISMATCH ? ? ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 190) #define WINHTTP_ERROR_LAST ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(WINHTTP_ERROR_BASE + 188) enum WINHTTP_WEB_SOCKET_BUFFER_TYPE ?{ ? WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE ? ? ? = 0, ? WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE ? ? ?= 1, ? WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE ? ? ? ? = 2, ? WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE ? ? ? ?= 3, ? WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE ? ? ? ? ? ? ? ?= 4 ?}; enum _WINHTTP_WEB_SOCKET_CLOSE_STATUS ?{ ? WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS ? ? ? ? ? ? ? ?= 1000, ? WINHTTP_WEB_SOCKET_ENDPOINT_TERMINATED_CLOSE_STATUS ? ?= 1001, ? WINHTTP_WEB_SOCKET_PROTOCOL_ERROR_CLOSE_STATUS ? ? ? ? = 1002, ? WINHTTP_WEB_SOCKET_INVALID_DATA_TYPE_CLOSE_STATUS ? ? ?= 1003, ? WINHTTP_WEB_SOCKET_EMPTY_CLOSE_STATUS ? ? ? ? ? ? ? ? ?= 1005, ? WINHTTP_WEB_SOCKET_ABORTED_CLOSE_STATUS ? ? ? ? ? ? ? ?= 1006, ? WINHTTP_WEB_SOCKET_INVALID_PAYLOAD_CLOSE_STATUS ? ? ? ?= 1007, ? WINHTTP_WEB_SOCKET_POLICY_VIOLATION_CLOSE_STATUS ? ? ? = 1008, ? WINHTTP_WEB_SOCKET_MESSAGE_TOO_BIG_CLOSE_STATUS ? ? ? ?= 1009, ? WINHTTP_WEB_SOCKET_UNSUPPORTED_EXTENSIONS_CLOSE_STATUS = 1010, ? WINHTTP_WEB_SOCKET_SERVER_ERROR_CLOSE_STATUS ? ? ? ? ? = 1011, ? WINHTTP_WEB_SOCKET_SECURE_HANDSHAKE_ERROR_CLOSE_STATUS = 1015 ?}; #define WINHTTP_WEB_SOCKET_MAX_CLOSE_REASON_LENGTH 123 #define WINHTTP_FLAG_SECURE ? ? ? ? ? ? ? ?0x00800000 #define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY ? ? ? ? ? ? ? 0 #define WINHTTP_OPTION_SECURITY_FLAGS ? ? ? ? ? ? ? ? ? 31 #define WINHTTP_OPTION_SECURE_PROTOCOLS ? ? ? ? ? ? ? ? 84 #define WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET ? ? ? ? ? ?114 #define WINHTTP_OPTION_WEB_SOCKET_CLOSE_TIMEOUT ? ? ? ? 115 #define WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL ? ?116 #define WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE ? 122 #define WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE ? ? ?123 #define SECURITY_FLAG_IGNORE_UNKNOWN_CA ? ? ? ? 0x00000100 #define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID ?0x00002000 #define SECURITY_FLAG_IGNORE_CERT_CN_INVALID ? ?0x00001000 #define SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE ? 0x00000200 #define ERROR_INVALID_PARAMETER ? ? ? ? ?87L #define ERROR_INVALID_OPERATION ? ? ? ? ?4317L #import "winhttp.dll" HINTERNET WinHttpOpen(string,DWORD,string,string,DWORD); HINTERNET WinHttpConnect(HINTERNET,string,INTERNET_PORT,DWORD); HINTERNET WinHttpOpenRequest(HINTERNET,string,string,string,string,string,DWORD); bool WinHttpSetOption(HINTERNET,DWORD,LPVOID[],DWORD); bool WinHttpQueryOption(HINTERNET,DWORD,LPVOID[],DWORD&); bool WinHttpSetTimeouts(HINTERNET,int,int,int,int); HINTERNET WinHttpSendRequest(HINTERNET,string,DWORD,LPVOID[],DWORD,DWORD,DWORD); bool WinHttpReceiveResponse(HINTERNET,LPVOID[]); HINTERNET WinHttpWebSocketCompleteUpgrade(HINTERNET,DWORD&); bool WinHttpCloseHandle(HINTERNET); DWORD WinHttpWebSocketSend(HINTERNET,WINHTTP_WEB_SOCKET_BUFFER_TYPE,BYTE&[],DWORD); DWORD WinHttpWebSocketReceive(HINTERNET,BYTE&[],DWORD,DWORD&,WINHTTP_WEB_SOCKET_BUFFER_TYPE&); DWORD WinHttpWebSocketClose(HINTERNET,ushort,BYTE&[],DWORD); DWORD WinHttpWebSocketQueryCloseStatus(HINTERNET,ushort&,BYTE&[],DWORD,DWORD&); #import //+------------------------------------------------------------------+