원시적인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밀리초) 의 타임아웃을 지정합니다.
- 다음 두 가지 매개 변수는 WebSocket에만 유효합니다:
매개 변수를 전달-1
함수는 메시지가 존재하거나 없더라도 즉시 반환하는 것을 의미합니다. 예를 들어:ws.read(-1)
...
매개 변수를 전달-2
함수는 메시지와 함께 또는 메시지가 없이 즉시 반환하지만, 최신 메시지가 반환되고 버퍼된 메시지가 폐기된다는 것을 의미합니다. 예를 들어,ws.read(-2)
.
The incoming data pushed by the WebSocket protocol may cause data accumulation if the time interval between strategy ```read()``` function calls is too long. These data are stored in the buffer, which has a data structure of a queue with a maximum of 2000. After 2000 is exceeded, the newest data enters the buffer and the oldest data is cleared out.
|Scenario|No parameter|Parameter: -1|Parameter: -2|Parameter: 2000, in milliseconds|
| - | - | - | - | - |
|Data already in the buffer|Return oldest data immediately|Return oldest data immediately|Return latest data immediately|Return oldest data immediately|
|No data in the buffer|Return when blocked to data|Return null immediately|Return null immediately|Wait 2000 ms, return null if no data, return null if there is data|
|WebSocket connection is disconnected or reconnected by the underlying |read() function returns the empty string, i.e.: "", and write() function returns 0. The situation is detected. You can close the connection using the close() function, or if you have set up automatic reconnection, you don't need to close it, the system underlying will reconnect it automatically.||||
object
Dial(address)
Dial(address, timeout)
Request address.
address
true
string
timeout seconds,
timeout
false
number
```javascript
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()
기능.
- 네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 프록시와 관련된 매개 변수: 프록시=파라미터 값 | 프록시 는 ss5 프록시 설정, 매개 변수 값 형식: 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)/yourdatabase?charset=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