> For the complete documentation index, see [llms.txt](https://docscn.jkidata.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docscn.jkidata.com/websocket-xie-yi-shuo-ming/2.-lian-jie.md).

# 📡 2. 连接

客户端必须先建立 WebSocket 连接并完成 API Key 验证，才能发送行情订阅、取消订阅和心跳指令。

### 连接地址

```
ws://jk:6610/websocket/json/{API_KEY}
```

将 `{API_KEY}` 替换为实际 API Key。

示例格式：

```
ws://jk:6610/websocket/json/your_api_key
```

> 文档示例统一使用 `your_api_key`，不要在公开文档、前端代码或日志中写入真实 API Key。

### 地址结构

| 地址部分               | 说明                |
| ------------------ | ----------------- |
| `ws://`            | WebSocket 协议      |
| `jk`               | 当前 WebSocket 服务节点 |
| `6610`             | WebSocket 服务端口    |
| `/websocket/json/` | JSON 数据连接路径       |
| `{API_KEY}`        | 用户的 API Key       |

### 连接流程

```
创建 WebSocket 客户端
        ↓
连接 WebSocket 地址
        ↓
等待服务端连接结果
        ↓
收到 connect: ok
        ↓
等待至少 5 秒
        ↓
发送订阅指令
```

### 连接成功

API Key 有效且连接建立成功后，服务端返回：

```
{
  "type": "connect",
  "msg": "ok"
}
```

字段说明：

| 字段     | 类型     | 说明                   |
| ------ | ------ | -------------------- |
| `type` | String | 消息类型，连接状态为 `connect` |
| `msg`  | String | `ok` 表示连接和认证成功       |

只有收到该消息后，才能认为 WebSocket 已经连接成功。

### 发送指令前等待5秒

收到以下连接成功消息后：

```
{
  "type": "connect",
  "msg": "ok"
}
```

客户端必须等待至少 5 秒，再发送第一条订阅或其他业务指令。

```
收到 connect: ok
        ↓
等待至少 5 秒
        ↓
发送订阅指令
```

不要仅根据 WebSocket 的 `open` 事件立即发送订阅。

正确判断方式：

```
WebSocket open
        ↓
收到 connect: ok
        ↓
等待5秒
        ↓
发送指令
```

### JavaScript连接示例

```
const API_KEY = "your_api_key";

const socket = new WebSocket(
  `ws://jk:6610/websocket/json/${API_KEY}`
);

let connectionReady = false;

socket.addEventListener("open", () => {
  console.log("WebSocket 已打开，正在等待认证结果");
});

socket.addEventListener("message", (event) => {
  const data = JSON.parse(event.data);

  if (
    !Array.isArray(data) &&
    data.type === "connect" &&
    data.msg === "ok"
  ) {
    console.log("WebSocket 连接成功");

    setTimeout(() => {
      connectionReady = true;
      console.log("现在可以发送订阅指令");
    }, 5000);

    return;
  }

  console.log("收到消息：", data);
});

socket.addEventListener("error", (error) => {
  console.error("WebSocket 连接错误：", error);
});

socket.addEventListener("close", (event) => {
  connectionReady = false;

  console.log(
    "WebSocket 已关闭",
    event.code,
    event.reason
  );
});
```

### Python连接示例

安装客户端：

```
pip install websocket-client
```

连接示例：

```
import json
import threading
import websocket

API_KEY = "your_api_key"

WS_URL = (
    "ws://jk:6610"
    f"/websocket/json/{API_KEY}"
)


def on_open(ws):
    print("WebSocket 已打开，正在等待认证结果")


def on_message(ws, message):
    data = json.loads(message)

    if (
        isinstance(data, dict)
        and data.get("type") == "connect"
        and data.get("msg") == "ok"
    ):
        print("WebSocket 连接成功")

        timer = threading.Timer(
            5.0,
            on_connection_ready,
            args=[ws],
        )
        timer.start()
        return

    print("收到消息：", data)


def on_connection_ready(ws):
    print("现在可以发送订阅指令")


def on_error(ws, error):
    print("WebSocket 错误：", error)


def on_close(ws, status_code, reason):
    print(
        "WebSocket 已关闭：",
        status_code,
        reason,
    )


client = websocket.WebSocketApp(
    WS_URL,
    on_open=on_open,
    on_message=on_message,
    on_error=on_error,
    on_close=on_close,
)

client.run_forever()
```

> 本页的连接示例只建立连接，不发送订阅。具体订阅代码请查看下一页“订阅行情”。

### API Key错误

使用错误或无效的 API Key 时，客户端可能出现以下情况：

```
WebSocket 已打开
        ↓
未收到 connect: ok
        ↓
连接被服务端关闭
```

实际验证中，错误 Key 未收到 JSON 错误消息，连接随后以状态码 `1006` 异常关闭。

因此，客户端不能只监听 `open` 事件，还必须等待：

```
{
  "type": "connect",
  "msg": "ok"
}
```

如果在设定时间内没有收到连接成功消息，应将本次连接判定为失败。

### 连接确认超时

建议为连接认证设置超时时间，例如15秒。

JavaScript示例：

```
const connectTimer = setTimeout(() => {
  if (!connectionReady) {
    console.error("未收到连接成功消息");

    socket.close();
  }
}, 15000);
```

收到 `connect: ok` 后取消认证超时：

```
clearTimeout(connectTimer);
```

### 连接数量限制

同一个 API Key 允许建立的并发连接数量为1，超过链接数的链接将无法链接。

达到连接数量限制时，服务端返回：

```
{
  "type": "connect",
  "msg": "This access key has reached the connection limit."
}
```

常见原因：

* 同一个 API Key 已在其他程序中连接。
* 上一次连接异常中断，服务端尚未释放会话。
* 程序重复创建了多个 WebSocket 客户端。
* 客户端退出时没有正常关闭连接。

建议：

* 每个程序复用已有 WebSocket 连接。
* 不要为每个产品单独建立连接。
* 多个市场和多个产品应通过同一连接订阅。
* 程序退出时主动关闭连接。
* 异常断线后不要立即高频重连。

### 数据格式

WebSocket 下行数据为 JSON 文本，但返回结构分为两种。

#### 状态消息

连接和订阅状态通常返回 JSON 对象：

```
{
  "type": "connect",
  "msg": "ok"
}
```

#### 行情消息

实时行情通常返回 JSON 数组：

```
[
  {
    "type": "quote",
    "msg": {
      "e": "JM",
      "s": "BTCUSDT"
    }
  }
]
```

客户端应先判断解析结果是否为数组，再进行后续处理。

### 压缩协议

WebSocket 服务支持：

```
permessage-deflate
```

压缩功能通常在握手阶段自动协商，主流 WebSocket 客户端会自动完成解压。

客户端收到的内容仍可直接按照 JSON 解析。

### 安全说明

当前连接地址使用：

```
ws://
```

`ws://` 不提供传输层加密，API Key 会作为连接路径的一部分发送。

使用时应注意：

* 不要在不可信网络中使用正式 API Key。
* 不要在日志中记录完整连接地址。
* 不要将 API Key 写入前端公开代码。
* API Key 应保存在服务端环境变量或密钥管理系统中。
* 怀疑密钥泄露时，应及时更换。
* 后续如提供 `wss://` 地址，应优先使用加密连接。

### 使用建议

* 收到 `connect: ok` 才表示连接和认证成功。
* 收到成功消息后至少等待5秒再发送指令。
* 不要在 `open` 回调中立即订阅。
* 同一个连接可订阅多个市场和多个产品。
* 不要为每个产品重复创建连接。
* 设置连接认证超时。
* 实现带延迟的断线重连。
* 连接失败时记录关闭代码，但不要记录完整 API Key。
* 订阅方式请继续查看下一页“订阅行情”。
