원시적인Socket
접근, 지원tcp
, udp
, tls
, unix
프로토콜 4개의 일반적인 통신 프로토콜을 지원합니다.mqtt
, nats
, amqp
, kafka
데이터베이스 연결을 지원합니다:sqlite3
, mysql
, postgres
, clickhouse
.
이Dial()
함수는 시간이 끝나면 null을 반환합니다. 정상적인 호출은 세 가지 메소드를 가진 연결 객체를 반환합니다.read
, write
그리고close
.read
이 방법은 데이터를 읽기 위해 사용됩니다.write
이 방법은 데이터를 전송하고close
이 방법은 연결을 닫는 데 사용됩니다.
의read
이 방법은 다음과 같은 매개 변수를 지원합니다.
ws.read()
.ws.read(2000)
2초 (2000밀리초) 의 타임아웃을 지정합니다.-1
함수는 메시지가 존재하거나 없더라도 즉시 반환하는 것을 의미합니다. 예를 들어:ws.read(-1)
...
매개 변수를 전달-2
함수는 메시지와 함께 또는 메시지가 없이 즉시 반환하지만, 최신 메시지가 반환되고 버퍼된 메시지가 폐기된다는 것을 의미합니다. 예를 들어,ws.read(-2)
.read()
함수 버퍼 설명:
웹소켓 프로토콜에 의해 밀어 입력 데이터는 전략 사이의 시간 간격이read()
함수 호출이 너무 길다. 이 데이터는 버퍼에 저장되며, 최대 2000의 대기열의 데이터 구조를 가지고 있습니다. 2000이 초과되면 가장 새로운 데이터가 버퍼에 입력되고 가장 오래된 데이터가 삭제됩니다.
시나리오 | 매개 변수가 없습니다. | 파라미터: -1 | 파라미터: -2 | 매개 변수: 2000 밀리 초 |
---|---|---|---|---|
이미 버퍼에 있는 데이터 | 가장 오래된 데이터를 즉시 반환 | 가장 오래된 데이터를 즉시 반환 | 최신 데이터를 즉시 반환 | 가장 오래된 데이터를 즉시 반환 |
버퍼에 데이터가 없습니다. | 데이터로 차단된 경우 반환 | 즉시 null을 반환합니다 | 즉시 null을 반환합니다 | 2000ms를 기다립니다. 데이터가 없다면 null을 반환합니다. 데이터가 있다면 null을 반환합니다. |
웹소켓 연결이 연결이 끊어지고 또는 기본에 의해 다시 연결 | read() 함수는 빈 문자열을 반환합니다. 즉: |
물체
전화번호 (주소) 전화 (주소, 시간)
주소 요청 주소 사실 문자열 타임아웃 초, 타임아웃 거짓 번호
function main(){
// Dial supports tcp://,udp://,tls://,unix://protocol, you can add a parameter to specify the number of seconds for the timeout
var client = Dial("tls://www.baidu.com:443")
if (client) {
// write can be followed by a numeric parameter to specify the timeout, write returns the number of bytes successfully sent
client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
while (true) {
// read can be followed by a numeric parameter specifying the timeout in milliseconds. Returning null indicates an error or timeout or that the socket has been closed
var buf = client.read()
if (!buf) {
break
}
Log(buf)
}
client.close()
}
}
def main():
client = Dial("tls://www.baidu.com:443")
if client:
client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
while True:
buf = client.read()
if not buf:
break
Log(buf)
client.close()
void main() {
auto client = Dial("tls://www.baidu.com:443");
if(client.Valid) {
client.write("GET / HTTP/1.1\nConnection: Closed\n\n");
while(true) {
auto buf = client.read();
if(buf == "") {
break;
}
Log(buf);
}
client.close();
}
}
다이얼 함수 호출 예제:
function main() {
LogStatus("Connecting...")
// Accessing WebSocket interface of Binance
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
if (!client) {
Log("Connection failed, program exited")
return
}
while (true) {
// read returns only the data retrieved after the read call
var buf = client.read()
if (!buf) {
break
}
var table = {
type: 'table',
title: 'Ticker Chart',
cols: ['Currency', 'Highest', 'Lowest', 'Buy 1', 'Sell 1', 'Last traded price', 'Volume', 'Update time'],
rows: []
}
var obj = JSON.parse(buf)
_.each(obj, function(ticker) {
table.rows.push([ticker.s, ticker.h, ticker.l, ticker.b, ticker.a, ticker.c, ticker.q, _D(ticker.E)])
})
LogStatus('`' + JSON.stringify(table) + '`')
}
client.close()
}
import json
def main():
LogStatus("Connecting...")
client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
if not client:
Log("Connection failed, program exited")
return
while True:
buf = client.read()
if not buf:
break
table = {
"type" : "table",
"title" : "Ticker Chart",
"cols" : ['Currency', 'Highest', 'Lowest', 'Buy 1', 'Sell 1', 'Last traded price', 'Volume', 'Update time'],
"rows" : []
}
obj = json.loads(buf)
for i in range(len(obj)):
table["rows"].append([obj[i]["s"], obj[i]["h"], obj[i]["l"], obj[i]["b"], obj[i]["a"], obj[i]["c"], obj[i]["q"], _D(int(obj[i]["E"]))])
LogStatus('`' + json.dumps(table) + '`')
client.close()
void main() {
LogStatus("Connecting...");
auto client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
if(!client.Valid) {
Log("Connection failed, program exited");
return;
}
while(true) {
auto buf = client.read();
if(buf == "") {
break;
}
json table = R"({
"type" : "table",
"title" : "Ticker Chart",
"cols" : ["Currency", "Highest", "Lowest", "Buy 1", "Sell 1", "Last traded price", "Volume", "Update time"],
"rows" : []
})"_json;
json obj = json::parse(buf);
for(auto& ele : obj.items()) {
table["rows"].push_back({ele.value()["s"], ele.value()["h"], ele.value()["l"], ele.value()["b"], ele.value()["a"], ele.value()["c"],
ele.value()["q"], _D(ele.value()["E"])});
}
LogStatus("`" + table.dump() + "`");
}
client.close();
}
바이낸스의 웹소켓 틱어 인터페이스에 액세스하려면:
var ws = null
function main(){
var param = {
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "BTC-USDT"
}]
}
// When calling Dial function, specify reconnect=true to set reconnection mode and payload to be the message sent when reconnecting. When the WebSocket connection is disconnected, it will reconnect and send messages automatically.
ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
if(ws){
var pingCyc = 1000 * 20
var lastPingTime = new Date().getTime()
while(true){
var nowTime = new Date().getTime()
var ret = ws.read()
Log("ret:", ret)
if(nowTime - lastPingTime > pingCyc){
var retPing = ws.write("ping")
lastPingTime = nowTime
Log("Send : ping", "#FF0000")
}
LogStatus("Current time:", _D())
Sleep(1000)
}
}
}
function onexit() {
ws.close()
Log("exit")
}
import json
import time
ws = None
def main():
global ws
param = {
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "BTC-USDT"
}]
}
ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload=" + json.dumps(param))
if ws:
pingCyc = 1000 * 20
lastPingTime = time.time() * 1000
while True:
nowTime = time.time() * 1000
ret = ws.read()
Log("ret:", ret)
if nowTime - lastPingTime > pingCyc:
retPing = ws.write("ping")
lastPingTime = nowTime
Log("Send: ping", "#FF0000")
LogStatus("Current time:", _D())
Sleep(1000)
def onexit():
ws.close()
Log("exit")
auto objWS = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true");
void main() {
json param = R"({
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "BTC-USDT"
}]
})"_json;
objWS.write(param.dump());
if(objWS.Valid) {
uint64_t pingCyc = 1000 * 20;
uint64_t lastPingTime = Unix() * 1000;
while(true) {
uint64_t nowTime = Unix() * 1000;
auto ret = objWS.read();
Log("ret:", ret);
if(nowTime - lastPingTime > pingCyc) {
auto retPing = objWS.write("ping");
lastPingTime = nowTime;
Log("Send: ping", "#FF0000");
}
LogStatus("Current time:", _D());
Sleep(1000);
}
}
}
void onexit() {
objWS.close();
Log("exit");
}
OKX
var ws = null
function main(){
var param = {"sub": "market.btcusdt.detail", "id": "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
if(ws){
while(1){
var ret = ws.read()
Log("ret:", ret)
// Respond to heartbeat packet operations
try {
var jsonRet = JSON.parse(ret)
if(typeof(jsonRet.ping) == "number") {
var strPong = JSON.stringify({"pong" : jsonRet.ping})
ws.write(strPong)
Log("Respond to ping, send pong:", strPong, "#FF0000")
}
} catch(e) {
Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
}
LogStatus("Current time:", _D())
Sleep(1000)
}
}
}
function onexit() {
ws.close()
Log("Execute the ws.close() function")
}
import json
ws = None
def main():
global ws
param = {"sub" : "market.btcusdt.detail", "id" : "id1"}
ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + json.dumps(param))
if ws:
while True:
ret = ws.read()
Log("ret:", ret)
# Respond to heartbeat packet operations
try:
jsonRet = json.loads(ret)
if "ping" in jsonRet and type(jsonRet["ping"]) == int:
strPong = json.dumps({"pong" : jsonRet["ping"]})
ws.write(strPong)
Log("Respond to ping, send pong:", strPong, "#FF0000")
except Exception as e:
Log("e:", e)
LogStatus("Current time:", _D())
Sleep(1000)
def onexit():
ws.close()
Log("Execute the ws.close() function")
using namespace std;
void main() {
json param = R"({"sub" : "market.btcusdt.detail", "id" : "id1"})"_json;
auto ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + param.dump());
if(ws.Valid) {
while(true) {
auto ret = ws.read();
Log("ret:", ret);
// Respond to heartbeat packet operations
try
{
auto jsonRet = json::parse(ret);
if(jsonRet["ping"].is_number()) {
json pong = R"({"pong" : 0})"_json;
pong["pong"] = jsonRet["ping"];
auto strPong = pong.dump();
ws.write(strPong);
Log("Respond to ping, send pong:", strPong, "#FF0000");
}
} catch(exception &e)
{
Log("e:", e.what());
}
LogStatus("Current time:", _D());
Sleep(1000);
}
}
}
void onexit() {
// ws.close();
Log("Execute the ws.close() function");
}
Huobi의 웹소켓 틱어 인터페이스에 액세스:
function getLogin(pAccessKey, pSecretKey, pPassphrase) {
// Signature function for login
var ts = (new Date().getTime() / 1000).toString()
var login = {
"op": "login",
"args":[{
"apiKey" : pAccessKey,
"passphrase" : pPassphrase,
"timestamp" : ts,
"sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey) // exchange.HMAC has been deprecated and is temporarily supported. Please use the latest exchange.Encode function instead.
}]
}
return login
}
var client_private = null
function main() {
// Because the read function uses a timeout setting, filtering the timeout reports errors that would otherwise be output with redundant errors
SetErrorFilter("timeout")
// Position channel subscription information
var posSubscribe = {
"op": "subscribe",
"args": [{
"channel": "positions",
"instType": "ANY"
}]
}
var accessKey = "xxx"
var secretKey = "xxx"
var passphrase = "xxx"
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000) // When logging in, you cannot subscribe to private channels immediately, you need to wait for server response
client_private.write(JSON.stringify(posSubscribe))
if (client_private) {
var lastPingTS = new Date().getTime()
while (true) {
var buf = client_private.read(-1)
if (buf) {
Log(buf)
}
// Detect disconnection, reconnect
if (buf == "" && client_private.write(JSON.stringify(posSubscribe)) == 0) {
Log("Disconnection detected, close connection, reconnect")
client_private.close()
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000)
client_private.write(JSON.stringify(posSubscribe))
}
// Send heartbeat packets
var nowPingTS = new Date().getTime()
if (nowPingTS - lastPingTS > 10 * 1000) {
client_private.write("ping")
lastPingTS = nowPingTS
}
}
}
}
function onexit() {
var ret = client_private.close()
Log("Close the connection!", ret)
}
import json
import time
def getLogin(pAccessKey, pSecretKey, pPassphrase):
ts = str(time.time())
login = {
"op": "login",
"args":[{
"apiKey" : pAccessKey,
"passphrase" : pPassphrase,
"timestamp" : ts,
"sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)
}]
}
return login
client_private = None
def main():
global client_private
SetErrorFilter("timeout")
posSubscribe = {
"op": "subscribe",
"args": [{
"channel": "positions",
"instType": "ANY"
}]
}
accessKey = "xxx"
secretKey = "xxx"
passphrase = "xxx"
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000)
client_private.write(json.dumps(posSubscribe))
if client_private:
lastPingTS = time.time() * 1000
while True:
buf = client_private.read(-1)
if buf:
Log(buf)
if buf == "" and client_private.write(json.dumps(posSubscribe)) == 0:
Log("Disconnection detected, close connection, reconnect")
ret = client_private.close()
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
Sleep(3000)
client_private.write(json.dumps(posSubscribe))
nowPingTS = time.time() * 1000
if nowPingTS - lastPingTS > 10 * 1000:
client_private.write("ping")
lastPingTS = nowPingTS
def onexit():
ret = client_private.close()
Log("Close the connection!", ret)
auto client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");
json getLogin(string pAccessKey, string pSecretKey, string pPassphrase) {
auto ts = std::to_string(Unix());
json login = R"({
"op": "login",
"args": [{
"apiKey": "",
"passphrase": "",
"timestamp": "",
"sign": ""
}]
})"_json;
login["args"][0]["apiKey"] = pAccessKey;
login["args"][0]["passphrase"] = pPassphrase;
login["args"][0]["timestamp"] = ts;
login["args"][0]["sign"] = exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey);
return login;
}
void main() {
SetErrorFilter("timeout");
json posSubscribe = R"({
"op": "subscribe",
"args": [{
"channel": "positions",
"instType": "ANY"
}]
})"_json;
auto accessKey = "xxx";
auto secretKey = "xxx";
auto passphrase = "xxx";
client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
Sleep(3000);
client_private.write(posSubscribe.dump());
if (client_private.Valid) {
uint64_t lastPingTS = Unix() * 1000;
while (true) {
auto buf = client_private.read(-1);
if (buf != "") {
Log(buf);
}
if (buf == "") {
if (client_private.write(posSubscribe.dump()) == 0) {
Log("Disconnection detected, close connection, reconnect");
client_private.close();
client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");
client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
Sleep(3000);
client_private.write(posSubscribe.dump());
}
}
uint64_t nowPingTS = Unix() * 1000;
if (nowPingTS - lastPingTS > 10 * 1000) {
client_private.write("ping");
lastPingTS = nowPingTS;
}
}
}
}
void onexit() {
client_private.close();
Log("exit");
}
OKX
var client = null
function main() {
// client = Dial("sqlite3://:memory:") // Using an in-memory database
client = Dial("sqlite3://test1.db") // Open/connect to the database file in the docker's directory
// record handle
var sqlite3Handle = client.fd()
Log("sqlite3Handle:", sqlite3Handle)
// Querying tables in the database
var ret = client.exec("SELECT name FROM sqlite_master WHERE type='table'")
Log(ret)
}
function onexit() {
Log("Execute client.close()")
client.close()
}
// Not supported
// Not supported
데이터베이스에 연결할 때 다이얼 함수가 반환하는 연결 객체는 두 가지 고유한 메소드 함수를 가지고 있습니다.
exec(sqlString)
: SQL 명령어를 실행하는 데 사용DBExec()
function.fd()
:fd()
함수는 다른 스레드가 다시 연결하기 위해 사용할 수 있는 핸들을 반환합니다. (디얼에 의해 생성된 객체가 실행에 의해 이미 닫혀있더라도)close()
연결을 닫는 기능)Dial()
예를 들어,Dial(handle)
재사용 연결
다음은 다이얼 기능의 예를sqlite3
database.세부 사항address
매개 변수,|
정상 주소 다음의 기호:wss://ws.okx.com:8443/ws/v5/public
만약|
매개 변수 문자열의 문자, 그리고||
분기 기호로 사용됩니다. 그 다음 부분은 몇 가지 함수 매개 변수 설정입니다.&
예를 들어,ss5
프록시와 압축 매개 변수는 다음과 같이 함께 설정될 수 있습니다.Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv")
다이얼 함수의 주소 매개 변수로 지원되는 함수 | 매개 변수 설명 |
---|---|
웹소켓 프로토콜 데이터 압축과 관련된 매개 변수: compress=parameter value | 압축은 압축 메소드, 압축 매개 변수 옵션은: gzip_raw, gzip, 등입니다. gzip 메소드가 표준 gzip이 아닌 경우 확장 메소드를 사용할 수 있습니다: gzip_raw |
웹소켓 프로토콜 데이터 압축과 관련된 매개 변수: mode=parameter value | 모드는 압축 모드, 모드 매개 변수는 듀얼이 될 수 있습니다. 전송, recv. 듀얼은 양방향 압축, 압축 데이터를 전송, 압축 데이터를 수신합니다. 전송은 압축 데이터를 전송합니다. recv는 압축 데이터를 수신합니다. 지역 압축 해제. |
웹소켓 프로토콜은 기본 자동 재연결 관련 매개 변수를 설정합니다: reconnect=parameter value | reconnect는 reconnect를 설정할 것인지, reconnect=true는 reconnect를 활성화할 것인지입니다. 이 매개 변수가 설정되지 않은 경우 기본값은 reconnect가 없습니다. |
웹소켓 프로토콜은 기본 자동 재연결 관련 매개 변수를 설정합니다: interval=parameter value | interval는 재시험 간격입니다. 밀리초로, interval=10000는 10초의 재시험 간격입니다. 기본값은 1초입니다. |
웹소켓 프로토콜은 기본 자동 재연결 관련 매개 변수를 설정합니다: payload=parameter value | payload는 웹소켓이 다시 연결될 때 보내야 하는 구독 메시지입니다. 예를 들어: payload=okokok |
소크스5 프록시와 관련된 매개 변수: 프록시=파라미터 값 | proxy는 ss5 proxy 설정, 매개 변수 값 형식: socks5://name:pwd@192.168.0.1:1080, 이름은 ss5 서버 사용자 이름, pwd는 ss5 서버 로그인 비밀번호, 1080는 ss5 서비스 포트입니다. |
이Dial()
이 기능은 라이브 트레이딩에서만 지원됩니다.
다이얼 함수를 사용하여 데이터베이스에 연결할 때, 연결 문자열은 각 데이터베이스의 go 언어 드라이버 프로젝트에 참조하여 작성됩니다.
지원되는 데이터베이스 | 추진 프로젝트 | 연결 문자열 | 언급 |
---|---|---|---|
스클라이트3 | github.com/mattn/go-sqlite3 | sqlite3://file:test.db?cache=shared&mode=memory | 이sqlite3:// 전자는 sqlite3 데이터베이스가 사용되고 있음을 나타냅니다. 예를 들어 호출:Dial("sqlite3://test1.db") |
mysql | github.com/go-sql-driver/mysql | mysql://username:yourpassword@tcp(localhost:3306) / 당신의 데이터베이스?차르셋=utf8mb4 | – |
포스트그레스 | github.com/lib/pq | postgres://user=postgres dbname=yourdatabase sslmode=disable password=yourpassword 호스트=localhost 포트=5432 | – |
클릭하우스 | github.com/ClickHouse/clickhouse-go | clickhouse://tcp://host:9000?username=username&password=yourpassword&database=youdatabase | – |
참고로,payload
내용address
매개 변수는 문자를 포함합니다.=
또는 다른 특수 문자, 그것은 분석에 영향을 미칠 수 있습니다address
매개 변수Dial
다음 예시처럼
backPack Exchange 웹소켓 개인 인터페이스 호출 예제:
var client = null
function main() {
// Base64-encoded public key of the key pair, i.e. the access key configured on FMZ
var base64ApiKey = "xxx"
var ts = String(new Date().getTime())
var data = "instruction=subscribe×tamp=" + ts + "&window=5000"
// Since signEd25519 returns a base64 encoding, it contains the character "="
var signature = signEd25519(data)
// The payload may contain the character "=" after being encoded by JSON
payload = {
"method": "SUBSCRIBE",
"params": ["account.orderUpdate"],
"signature": [base64ApiKey, signature, ts, "5000"]
}
client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))
if (!client) {
Log("Connection failed, program exited")
return
}
while (true) {
var buf = client.read()
Log(buf)
}
}
function onexit() {
client.close()
}
function signEd25519(data) {
return exchange.Encode("ed25519.seed", "raw", "base64", data, "base64", "{{secretkey}}")
}
코드의 다음 호출은 잘 작동합니다.
client = Dial("wss://ws.backpack.exchange")
client.write(JSON.stringify(payload))
만약 당신이 그것을 직접payload
, 그것은 제대로 작동하지 않습니다, 예를 들어:
client = Dial("wss://ws.backpack.exchange|payload=" + JSON.stringify(payload))
현재 자바스크립트만이mqtt
, nats
, amqp
, 그리고kafka
다이얼 함수에서 통신 프로토콜. 자바스크립트 언어 전략 코드는 네 개의 프로토콜의 사용을 보여주는 예로 사용됩니다.mqtt
, nats
, amqp
, 그리고kafka
:
// We need to configure and deploy proxy servers for each protocol first.
// For the sake of demonstration, the subscription (read operation) and publishing (write operation) of the topic test_topic are all performed in the current strategy.
var arrConn = []
var arrName = []
function main() {
LogReset(1)
conn_nats = Dial("nats://admin@127.0.0.1:4222?topic=test_topic")
conn_mqtt = Dial("mqtt://127.0.0.1:1883?topic=test_topic")
conn_amqp = Dial("amqp://q:admin@127.0.0.1:5672/?queue=test_Queue")
conn_kafka = Dial("kafka://localhost:9092/test_topic")
arrConn = [conn_nats, conn_amqp, conn_mqtt, conn_kafka]
arrName = ["nats", "amqp", "mqtt", "kafka"]
while (true) {
for (var i in arrConn) {
var conn = arrConn[i]
var name = arrName[i]
// Write data
conn.write(name + ", time: " + _D() + ", test msg.")
// Read data
var readMsg = conn.read(1000)
Log(name + " readMsg: ", readMsg, "#FF0000")
}
Sleep(1000)
}
}
function onexit() {
for (var i in arrConn) {
arrConn[i].close()
Log("close", arrName[i], "connect")
}
}
자세한 문서 참조:FMZ를 탐구: 라이브 거래 전략 사이의 통신 프로토콜의 연습
GetMeta HttpQuery