精华内容
下载资源
问答
  • 主要介绍了微信小程序 网络API Websocket详解的相关资料,需要的朋友可以参考下
  • Fastapi Websocket 简明使用 1.基于Fastapi 开发websocket 服务器端 2.基于Fastapi 开发websocket 客户端 环境 github python3.7 win10 依赖 pip install fastapi[all] websocket-client -i ...

    Fastapi Websocket 简明使用

    • 1.基于Fastapi 开发websocket 服务器端
    • 2.基于Fastapi 开发websocket 客户端
      在这里插入图片描述

    环境

    • github
    • python3.7
    • win10
    • 依赖
    	 pip install fastapi[all] websocket-client -i https://pypi.doubanio.com/simple
    

    基于fastapi 实现 weboskcet

    • main.py
    from typing import List
    
    from fastapi import FastAPI, WebSocket, WebSocketDisconnect
    from fastapi.responses import HTMLResponse
    
    app = FastAPI()
    
    html = """
    <!DOCTYPE html>
    <html>
        <head>
            <title>Chat</title>
        </head>
        <body>
            <h1>WebSocket Chat</h1>
            <h2>Your ID: <span id="ws-id"></span></h2>
            <form action="" οnsubmit="sendMessage(event)">
                <input type="text" id="messageText" autocomplete="off"/>
                <button>Send</button>
            </form>
            <ul id='messages'>
            </ul>
            <script>
                var client_id = Date.now()
                document.querySelector("#ws-id").textContent = client_id;
                var ws = new WebSocket(`ws://192.168.144.81:8000/ws/${client_id}`);
                ws.onmessage = function(event) {
                    var messages = document.getElementById('messages')
                    var message = document.createElement('li')
                    var content = document.createTextNode(event.data)
                    message.appendChild(content)
                    messages.appendChild(message)
                };
                function sendMessage(event) {
                    var input = document.getElementById("messageText")
                    ws.send(input.value)
                    input.value = ''
                    event.preventDefault()
                }
            </script>
        </body>
    </html>
    """
    
    
    class ConnectionManager:
        def __init__(self):
            self.active_connections: List[WebSocket] = []
    
        async def connect(self, websocket: WebSocket):
            await websocket.accept()
            self.active_connections.append(websocket)
    
        def disconnect(self, websocket: WebSocket):
            self.active_connections.remove(websocket)
    
        async def send_personal_message(self, message: str, websocket: WebSocket):
            await websocket.send_text(message)
    
        async def broadcast(self, message: str):
            for connection in self.active_connections:
                await connection.send_text(message)
    
    
    manager = ConnectionManager()
    
    
    @app.get("/")
    async def get():
        return HTMLResponse(html)
    
    
    @app.websocket("/ws/{client_id}")
    async def websocket_endpoint(websocket: WebSocket, client_id: int):
        await manager.connect(websocket)
        try:
            while True:
                data = await websocket.receive_text()
    
                await manager.send_personal_message(f"You wrote: {data}", websocket)
                await manager.broadcast(f"Client #{client_id} says: {data}")
        except WebSocketDisconnect:
            manager.disconnect(websocket)
            await manager.broadcast(f"Client #{client_id} left the chat")
    
    if __name__ == "__main__":
        import uvicorn
        uvicorn.run(
            app='main:app', 
            host="0.0.0.0",
            log_level="debug", 
            port=8000,
            loop="asyncio",
            # workers=4,
        )
    
    • client.py
    from fastapi import FastAPI,BackgroundTasks
    from starlette.concurrency import run_in_threadpool
    def create_app():
        app = FastAPI()
        return app
    
    app = create_app()
    
    @app.on_event("startup")
    async def init_scheduler():
        from task import run
        run()
       
        
    
    if __name__ =='__main__':
        import uvicorn
        uvicorn.run(
            app='client:app', 
            host="0.0.0.0",
            log_level="debug", 
            port=8888,
            loop="asyncio",
            # workers=4,
        )
    
    • task.py
    import websocket
    import threading, time
    
    def on_close(ws):
    	'''
    		- websocket client 重试机制
    	'''
        print ("Retry : %s" % time.ctime())
        time.sleep(2)
        connect_websocket() # 每2s 重试一次
    def on_open(ws):
    	'''
    		- 当系统连接上后的提示
    	'''
        print('connection established')
    
    def on_message(wsapp, message):
    	'''
    		- 接收服务器websocket 发送来的消息
    	'''
        print(message)
    
    def connect_websocket():
    	'''
    		- 尝试连接websocket 服务器
    		- 并给该线程设置守护
    	'''
        ws = websocket.WebSocketApp(
            "ws://192.168.144.81:8000/ws/2323", 
            on_open = on_open, 
            on_close = on_close,
            cookie="chocolate",
            on_message=on_message
            )
        wst = threading.Thread(target=ws.run_forever)
        wst.daemon = True
        wst.start()
    
    def run():
    '''
    	- websocket 组件会跟随fastapi 主进程启动
    	- 客户端系统会每隔2s 尝试一次连接
    '''
        try:
            connect_websocket()
        except Exception as err:
            print(err)
            print("connect failed")
    

    在这里插入图片描述在这里插入图片描述

    展开全文
  • 火币Huobi API Websocket

    千次阅读 2018-11-08 18:11:00
    本文介绍火币Huobi API Websocket WebSocket API简介 WebSocket协议是基于TCP的一种新的网络协议。它实现了客户端与服务器之间在单个 tcp 连接上的全双工通信,由服务器主动发送信息给客户端,减少了频繁的身份验证...

     本文介绍火币Huobi API Websocket

     

    WebSocket API简介

    WebSocket协议是基于TCP的一种新的网络协议。它实现了客户端与服务器之间在单个 tcp 连接上的全双工通信,由服务器主动发送信息给客户端,减少了频繁的身份验证等不必要的开销。其最大优点有两个:

    • 两方请求的 header 数据很小,大概只有2 Bytes。

    • 服务器不再是被动的接到客户端的请求后才返回数据,而是有了新数据后主动推送给客户端。

    以上 WebSocket 协议带来的优点使得其十分适用于数字货币行情和交易这种实时性强的接口。

    WebSocket 只支持行情查询、订单和资产推送,交易接口将在后续提供。在使用中如果遇到问题,请加技术讨论 QQ 群: 火币网API交流群(7) 794370631,我们将尽力帮您答疑解惑(加群时请注明uid和编程语言)。

     

    请求与订阅说明

    1. 访问地址

    注意:HADAX和Pro是两个不同的交易站,所以行情信息也不一样,请通过 Pro symbols 和 HADAX symbols 查询相应的交易对信息

    • Pro 站行情请求地址为:wss://api.huobi.pro/ws
    • HADAX 站行情请求地址为:wss://api.hadax.com/ws
    • Pro 站和 HADAX 站资产和订单推送统一服务地址为:wss://api.huobi.pro/ws/v1

    2. 数据压缩

    WebSocket API 返回的所有数据都进行了 GZIP 压缩,需要 client 在收到数据之后解压,推荐使用pako。(【pako】 是一个支持压缩和解压 GZIP 的库)

    3. WebSocket库

    【ws】 是 Node.js 下的 WebSocket 库。

    4. 心跳

    WebSocket API 支持双向心跳,无论是 Server 还是 Client 都可以发起 ping message,对方返回 pong message。

    WebSocket Server 发送心跳:

    {"ping": 18212558000}
    

    WebSocket Client 应该返回:

     {"pong": 18212558000}
    

    注:返回的数据里面的 "pong" 的值为收到的 "ping" 的值 注:WebSocket Client 和 WebSocket Server 建立连接之后,WebSocket Server 每隔 5s(这个频率可能会变化) 会向 WebSocket Client 发起一次心跳,WebSocket Client 忽略心跳2次后,WebSocket Server 将会主动断开连接;WebSocket Client发送最近2次心跳message中的其中一个ping的值,WebSocket Server都会保持WebSocket连接。

    ┌────────┐                         ┌────────┐ 
    │ Client │                         │ Server │
    └───┬────┘                         └───┬────┘
        │         {"ping": 18212558000}  │
        │<─────────────────────────────────┤
        │                                  │ wait 5s
        │                                  ├───┐
        │                                  │<──┘
        │         {"ping": 18212558000}  │
        │<─────────────────────────────────┤
        │                                  │
        │ {"pong": 18212558000}          │
        ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄>│
        │                                  │
    

    注:WebSocket Client 发送最近2次心跳 message 中的其中一个 "ping" 的值,WebSocket Server 都会保持 WebSocket 连接

    ┌────────┐                         ┌────────┐ 
    │ Client │                         │ Server │
    └───┬────┘                         └───┬────┘
        │         {"ping": 1523778470416}  │
        │<─────────────────────────────────┤
        │                                  │ wait 5s
        │                                  ├───┐
        │                                  │<──┘
        │         {"ping": 1523778475416}  │
        │<─────────────────────────────────┤
        │                                  │ wait 5s
        │                                  ├───┐
        │                                  │<──┘
        │                                  │
        │                                  │ close WebSocket connection
        │                                  ├───┐
        │                                  │<──┘
        │                                  │
    
    

    注:WebSocket Client 忽略心跳2次后,WebSocket Server 将会主动断开连接。 WebSocket Client 发送心跳:

    {"ping": 18212553000}
    

    注:发送的 message 里面,"ping" 的值必须为 Long 类型,否则返回错误信息:

    {
      "ts": 1492420473027,
      "status": "error",
      "err-code": "bad-request",
      "err-msg": "invalid ping"
    }
    

    WebSocket Server 会返回:

    {"pong": 18212553000}
    

    注:返回的数据里面的 "pong" 的值为收到的 "ping" 的值

    错误信息返回格式

    {
      "id": "id generate by client",
      "status": "error",
      "err-code": "err-code",
      "err-msg": "err-message",
      "ts": 1487152091345
    }
    

    注:ts为错误信息生成的时间戳,单位:毫秒

    5. topic格式

    订阅数据和请求数据都要使用 topictopic 的语法如下:

    topic 类型topic 语法sub/req描述是否需要验签
    KLine market.$symbol.kline.$period sub/req K线 数据,包含单位时间区间的开盘价、收盘价、最高价、最低价、成交量、成交额、成交笔数等数据 $period 可选值:{ 1min, 5min, 15min, 30min, 60min, 4hour,1day, 1mon, 1week, 1year } N
    Market Depth market.$symbol.depth.$type sub/req 盘口深度,按照不同 step 聚合的买一、买二、买三等和卖一、卖二、卖三等数据 $type 可选值:{ step0, step1, step2, step3, step4, step5, percent10 } (合并深度0-5);step0时,不合并深度 N
    Trade Detail market.$symbol.trade.detail sub/req 成交记录,包含成交价格、成交量、成交方向等信息 N
    Market Detail market.$symbol.detail sub/req 最近24小时成交量、成交额、开盘价、收盘价、最高价、最低价、成交笔数等 N
    Market Tickers market.tickers sub 所有对外公开交易对的 日K线、最近24小时成交量等信息 N
    Accounts accounts sub, unsub 订阅账户资产变更 Y
    Orders orders.$symbol sub,unsub 订阅订单变更 Y
    Accounts list accounts.list req 请求账户资产信息 Y
    Order list accounts.list req 请求订单信息 Y
    order detail orders.detail req 请求某个订单明细 Y
    • $symbol 为交易对,可选值: { ethbtc, ltcbtc, etcbtc, bchbtc...... }
    • 用户选择“合并深度”时,一定报价精度内的市场挂单将予以合并显示。合并深度仅改变显示方式,不改变实际成交价格。

    6. 请求数据(req/rep)

    请求数据,仅返回一次数据

    请求数据的格式

    {
      "req": "topic to req",
      "id": "id generate by client"
    }
    
    • "req" 的值为 topic ,请参考 "5. topic格式" 的 topic 格式

    正确请求数据的例子

    {
      "req": "market.btcusdt.kline.1min",
      "id": "id10"
    }
    

    返回数据的例子:

    {
      "status": "ok",
      "rep": "market.btcusdt.kline.1min",
      "tick": [
        {
          "amount": 1.6206,
          "count":  3,
          "id":     1494465840,
          "open":   9887.00,
          "close":  9885.00,
          "low":    9885.00,
          "high":   9887.00,
          "vol":    16021.632026
        },
        {
          "amount": 2.2124,
          "count":  6,
          "id":     1494465900,
          "open":   9885.00,
          "close":  9880.00,
          "low":    9880.00,
          "high":   9885.00,
          "vol":    21859.023500
        }
      ]
    }
    

    错误请求数据的例子

    {
      "req": "market.invalidsymbo.kline.1min",
      "id": "id10"
    }
    

    返回的错误信息的例子:

    {
      "status": "error",
      "id": "id10",
      "err-code": "bad-request",
      "err-msg": "invalid topic market.invalidsymbol.trade.detail",
      "ts": 1494483996521
    }
    

    7. 订阅数据(sub)

    订阅数据(sub)以及接收订阅数据的大致流程

    ┌────────┐                         ┌────────┐ 
    │ Client │                         │ Server │
    └───┬────┘                         └───┬────┘
        │ {"sub": "topic"}                 │
        ├─────────────────────────────────>│
        │                                  │
        │              {"subbed": "topic"} │
        │<┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤
        │                                  │
        │        {"tick": "data of topic"} │
        │<┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤
        │                                  │
        │        {"tick": "data of topic"} │
        │<┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤
        │                                  │
    

    注:订阅 topic 成功之后,当 topic 对应的数据有更新时,Server 按一定的频率把 topic 对应的新数据推送给 Client

    订阅数据的格式

    成功建立和 WebSocket API 的连接之后,向 Server 发送如下格式的数据来订阅数据:

    {
       "id": "id generate by client",
      "sub": "topic to sub",
      "freq-ms": 1000
    }
    

    注:id 参数是可选的 注:freq-ms 参数是可选的,可选值为 { 10002000300040005000},不传 freq-ms 时默认为0也就是有新的数据就马上推送到 Client,freq-ms 决定 Server 推送的频率 正确订阅的例子

    正确订阅:

    {
      "sub": "market.btcusdt.kline.1min",
      "id": "id1"
    }
    
    • "sub" 的值为 topic ,请参考 "5. topic格式" 的 topic 格式

    订阅成功返回数据的例子:

    {
      "id": "id1",
      "status": "ok",
      "subbed": "market.btcusdt.kline.1min",
      "ts": 1489474081631
    }
    

    之后每当 KLine 有更新时,client 会收到数据,例子:

    {
      "ch": "market.btcusdt.kline.1min",
      "ts": 1489474082831,
      "tick": {
        "id": 1489464480,
        "amount": 0.0,
        "count": 0,
        "open": 7962.62,
        "close": 7962.62,
        "low": 7962.62,
        "high": 7962.62,
        "vol": 0.0
      }
    }
    

    tick 说明:

      "tick": {
        "id": K线id,
        "amount": 成交量,
        "count": 成交笔数,
        "open": 开盘价,
        "close": 收盘价,当K线为最晚的一根时,是最新成交价
        "low": 最低价,
        "high": 最高价,
        "vol": 成交额, 即 sum(每一笔成交价 * 该笔的成交量)
      }
    
    

    错误订阅的例子

    错误订阅(错误的 symbol):

    {
      "sub": "market.invalidsymbol.kline.1min",
      "id": "id2"
    }
    

    订阅失败返回数据的例子:

    {
      "id": "id2",
      "status": "error",
      "err-code": "bad-request",
      "err-msg": "invalid topic market.invalidsymbol.kline.1min",
      "ts": 1494301904959
    }
    

    错误订阅(错误的 topic):

    {
      "sub": "market.btcusdt.kline.3min",
      "id": "id3"
    }
    

    订阅失败返回数据的例子:

    {
      "id": "id3",
      "status": "error",
      "err-code": "bad-request",
      "err-msg": "invalid topic market.btcusdt.kline.3min",
      "ts": 1494310283622
    }
    

    8. 取消订阅(unsub)

    取消订阅的格式

    WebSocket Client 订阅数据之后,可以取消订阅,取消订阅之后 WebSocket Server 将不会再发送该 topic 的数据,取消订阅的格式如下:

    {
      "unsub": "topic to unsub",
      "id": "id generate by client"
    }
    

    正确取消订阅的例子

    正确取消订阅的例子:

    {
      "unsub": "market.btcusdt.trade.detail",
      "id": "id4"
    }
    

    取消订阅成功返回信息的例子:

    {
      "id": "id4",
      "status": "ok",
      "unsubbed": "market.btcusdt.trade.detail",
      "ts" 1494326028889
    }
    

    错误取消订阅的例子

    错误取消订阅的例子(取消订阅一个尚未订阅的 topic):

    {
      "unsub": "market.btcusdt.trade.detail",
      "id": "id5"
    }
    

    返回的错误信息的例子

    {
      "id": "id5",
      "status": "error",
      "err-code": "bad-request",
      "err-msg": "unsub with not subbed topic market.btcusdt.trade.detail",
      "ts": 1494326217428
    }
    

    错误取消订阅的例子(取消订阅一个不存在的 topic):

    {
      "unsub": "not-exists-topic",
      "id": "id5"
    }
    

    返回的错误信息的例子:

    {
      "id": "id5",
      "status": "error",
      "err-code": "bad-request",
      "err-msg": "unsub with not subbed topic not-exists-topic",
      "ts": 1494326318809
    }
    

    9. 鉴权(Authentication)

    用户自己在火币网生成Access Key和Secret Key,Secret Key由用户自己保存,用户需提供Access Key。目前关于 apikey 申请和修改,请在“账户 - API 管理 ” 创建新API Key 填写备注(可选择绑定ip)点击创建。其中 Access Key 为 API 访问密钥,Secret Key 为用户对请求进行签名的密钥(仅申请时可见)。用户按规则生成签名(Signature)。Pro 站和 HADAX 站 apikey 通用。

    交易功能 websocket 版本接口建立连接时首先要做鉴权操作,具体格式如下,

    重要提示:这两个密钥与账号安全紧密相关,无论何时都请勿向其它人透露。

    鉴权请求数据格式

    {
      "op": "auth",
      "AccessKeyId": "e2xxxxxx-99xxxxxx-84xxxxxx-7xxxx", 
      "SignatureMethod": "HmacSHA256",
      "SignatureVersion": "2",
      "Timestamp": "2017-05-11T15:19:30",
      "Signature": "4F65x5A2bLyMWVQj3Aqp+B4w+ivaA7n5Oi2SuYtCJ9o=",
    }
    

    鉴权请求数据格式说明

    字段名称类型说明
    op string 必填;操作名称,鉴权固定值为 auth;
    cid string 选填;Client 请求唯一 ID
    AccessKeyId string 必填;API 访问密钥, 您申请的 APIKEY 中的 AccessKey
    SignatureMethod string 必填;签名方法, 用户计算签名的基于哈希的协议,此处使用 HmacSHA256
    SignatureVersion string 必填;签名协议的版本,此处使用 2
    Timestamp string 必填;时间戳, 您发出请求的时间 (UTC 时区) (UTC 时区) (UTC 时区) 。在查询请求中包含此值有助于防止第三方截取您的请求。如:2017-05-11T16:22:06。再次强调是 (UTC 时区)
    Signature string 必填;签名, 计算得出的值,用于确保签名有效和未被篡改

    注意:

    • 为了减少已有用户的接入工作量,此处使用了与 REST 接口同样的签名算法进行鉴权,详细请参考 REST_authentication#签名运算
    • 请注意大小写
    • 参数 opcidSignature 不参加签名计算
    • 此处签名计算中请求方法固定值为GET,其余值请参考 REST 接口签名算法文档

    步骤:

    示例参数签名(Signature)计算过程如下,

    • 规范要计算签名的请求 因为使用 HMAC 进行签名计算时,使用不同内容计算得到的结果会完全不同。所以在进行签名计算前,请先对请求进行规范化处理。

    • 请求方法,后面添加换行符\n

    GET\n
    
    • 添加小写的访问地址,后面添加换行符 \n
    api.huobipro.com\n
    
    • 访问方法的路径,后面添加换行符 \n
    /ws/v1\n
    
    • 按照ASCII码的顺序对参数名进行排序(使用 UTF-8 编码,且进行了 URI 编码,十六进制字符必须大写,如‘:’会被编码为'%3A',空格被编码为'%20')。 例如,下面是请求参数的原始顺序,进行过编码后。
    AccessKeyId=e2xxxxxx-99xxxxxx-84xxxxxx-7xxxx&Signature
    Method=HmacSHA256&SignatureVersion=2&Timestamp=2017-05-11T15%
    3A19%3A30
    
    • 按照以上顺序,将各参数使用字符’&’连接。
      • 组成最终的要进行签名计算的字符串如下:
        • 计算签名,将以下两个参数传入加密哈希函数: 要进行签名计算的字符串,进行签名的密钥(SecretKey)
        • 得到签名计算结果并进行 Base64编码
    • 将上述值作为参数Signature的取值添加到 API 请求中。 将此参数添加到请求时,必须将该值进行 URI 编码。

    鉴权应答数据格式说明

    名称类型说明
    op string 必填;操作名称,鉴权固定值为 auth
    err-code integer 成功返回 0, 失败为其他值,详细响应码列表请参考附录
    err-msg string 可选,若出错表示详细错误信息
    ts long 服务端应答时间戳
    user-id long 用户 id

    鉴权成功应答数据示例

    {
      "op": "auth",
      "ts": 1489474081631,
      "err-code": 0,
      "data": {
        "user-id": 1000
      }
    }
    

    鉴权失败应答返回数据

    {
      "op": "auth",
      "ts": 1489474081631,
      "err-code": 1010,
      "err-msg": ”详细的错误信息“
    }
    

    若用户上一次鉴权还未应答,用户连续发送鉴权请求,会返回重复鉴权的错误应答:

    {
      "op": "auth",
      "ts": 1489474081631,
      "err-code": 1022,
      "err-msg": ”详细的错误信息“
    }

     

    WebSocket API Reference

    订阅 KLine 数据 market.$symbol.kline.$period

    成功建立和 WebSocket API 的连接之后,向 Server 发送如下格式的数据来订阅数据:

    {
      "sub": "market.$symbol.kline.$period",
      "id": "id generate by client"
    }
    
    参数名称是否必须类型描述默认值取值范围
    symbol true string 交易对   ethbtc, ltcbtc, etcbtc, bchbtc......以下新的symbol会在生效日当天可以请求:huobi10 - 指数,hb10 - ETF净值
    period true string K线周期   1min, 5min, 15min, 30min, 60min, 1day, 1mon, 1week, 1year

    正确订阅的例子

    正确订阅

    {
      "sub": "market.btcusdt.kline.1min",
      "id": "id1"
    }
    

    订阅成功返回数据的例子

    {
      "id": "id1",
      "status": "ok",
      "subbed": "market.btcusdt.kline.1min",
      "ts": 1489474081631
    }
    

    之后每当 KLine 有更新时,client 会收到数据,例子

    {
      "ch": "market.btcusdt.kline.1min",
      "ts": 1489474082831,
      "tick": {
        "id": 1489464480,
        "amount": 0.0,
        "count": 0,
        "open": 7962.62,
        "close": 7962.62,
        "low": 7962.62,
        "high": 7962.62,
        "vol": 0.0
      }
    }

    tick 说明

      "tick": {
        "id": K线id,
        "amount": 成交量,
        "count": 成交笔数,
        "open": 开盘价,
        "close": 收盘价,当K线为最晚的一根时,是最新成交价
        "low": 最低价,
        "high": 最高价,
        "vol": 成交额, 即 sum(每一笔成交价 * 该笔的成交量)
      }
    
    

    错误订阅的例子

    错误订阅(错误的 symbol)

    {
      "sub": "market.invalidsymbol.kline.1min",
      "id": "id2"
    }
    

    订阅失败返回数据的例子

    {
      "id": "id2",
      "status": "error",
      "err-code": "bad-request",
      "err-msg": "invalid topic market.invalidsymbol.kline.1min",
      "ts": 1494301904959
    }

    错误订阅(错误的 topic)

    {
      "sub": "market.btcusdt.kline.3min",
      "id": "id3"
    }
    

    订阅失败返回数据的例子

    {
      "id": "id3",
      "status": "error",
      "err-code": "bad-request",
      "err-msg": "invalid topic market.btcusdt.kline.3min",
      "ts": 1494310283622
    }

    请求 KLine 数据 market.$symbol.kline.$period

    {
      "req": "market.$symbol.kline.$period",
      "id": "id generated by client",
      "from": 1533536947, //optional, type: long, 2017-07-28T00:00:00+08:00 至 2050-01-01T00:00:00+08:00 之间的时间点,单位:秒
      "to": 1533536947 //optional, type: long, 2017-07-28T00:00:00+08:00 至 2050-01-01T00:00:00+08:00 之间的时间点,单位:秒,必须比 from 大
    }
    
    参数名称是否必须类型描述默认值取值范围
    symbol true string 交易对   btcusdt, ethusdt, ltcusdt, etcusdt, bchusdt, ethbtc, ltcbtc, etcbtc, bchbtc... 以下新的symbol会在生效日当天可以请求:huobi10 - 指数,hb10 - ETF净值
    period true string K线周期   1min, 5min, 15min, 30min, 60min, 1day, 1mon, 1week, 1year
    关于ETF请求参数的说明
    Symbol说明
    huobi10 指数
    hb10 ETF净值

    其他请求参数period,from,to保持不变。

    • 响应结果

    响应结果的结构保持不变,唯一的区别是响应结果中的amount, count 和 vol都是0,因为在这里的amount, count 和 vol是交易的相关的 值,而指数和ETF净值没有相应的数据。Houbi10 指数和 Hb10净值每15秒更新一次。

    [t1, t5] 假设有 t1 ~ t5 的K线.

    • from: t1, to: t5, return [t1, t5].
    • from: t5, to: t1, which t5 > t1, return [].
    • from: t5, return [t5].
    • from: t3, return [t3, t5].
    • to: t5, return [t1, t5].
    • from: t which t3 < t <t4, return [t4, t5].
    • to: t which t3 < t <t4, return [t1, t3].
    • from: t1 and to: t2, should satisfy 1501171200 < t1 < t2 < 2524579200.
    一次最多300条
    

    请求 KLine 数据的例子

    {
      "req": "market.btcusdt.kline.1min",
      "id": "id10"
    }
    

    返回数据的例子

    {
      "rep": "market.btcusdt.kline.1min",
      "status": "ok",
      "id": "id10",
      "tick": [
        {
          "amount": 17.4805,
          "count":  27,
          "id":     1494478080,
          "open":   10050.00,
          "close":  10058.00,
          "low":    10050.00,
          "high":   10058.00,
          "vol":    175798.757708
        },
        {
          "amount": 15.7389,
          "count":  28,
          "id":     1494478140,
          "open":   10058.00,
          "close":  10060.00,
          "low":    10056.00,
          "high":   10065.00,
          "vol":    158331.348600
        },
        // more KLine data here
      ]
    }
    

    订阅 Market Depth 数据 market.$symbol.depth.$type

    成功建立和 WebSocket API 的连接之后,向 Server 发送如下格式的数据来订阅数据:

    {
      "sub": "market.$symbol.depth.$type",
      "id": "id generated by client"
    }
    
    参数名称是否必须类型描述默认值取值范围
    symbol true string 交易对   btcusdt, ethusdt, ltcusdt, etcusdt, bchusdt, ethbtc, ltcbtc, etcbtc, bchbtc...
    type true string Depth 类型   step0, step1, step2, step3, step4, step5(合并深度0-5);step0时,不合并深度

    用户选择“合并深度”时,一定报价精度内的市场挂单将予以合并显示(具体合并规则见GET /market/symbols)。合并深度仅改变显示方式,不改变实际成交价。

    正确订阅例子

    {
      "sub": "market.btcusdt.depth.step0",
      "id": "id1"
    }
    

    订阅成功返回数据的例子

    {
      "id": "id1",
      "status": "ok",
      "subbed": "market.btcusdt.depth.step0",
      "ts": 1489474081631
    }
    

    之后每当 depth 有更新时,client 会收到数据,例子

    {
      "ch": "market.btcusdt.depth.step0",
      "ts": 1489474082831,
      "tick": {
        "bids": [
        [9999.3900,0.0098], // [price, amount]
        [9992.5947,0.0560],
        // more Market Depth data here
        ]
        "asks": [
        [10010.9800,0.0099]
        [10011.3900,2.0000]
        //more data here
        ]
      }
    }
    

    tick 说明

      "tick": {
        "bids": [
        [买1价,买1量]
        [买2价,买2量]
        //more data here
        ]
        "asks": [
        [卖1价,卖1量]
        [卖2价,卖2量]
        //more data here
        ]
      }
    

    请求 Market Depth 数据 market.$symbol.depth.$type

    {
      "req": "market.$symbol.depth.$type",
      "id": "id generated by client"
    }
    

    请求 Market Depth 数据的例子

    {
      "req": "market.btcusdt.depth.step0",
      "id": "id10"
    }
    

    返回数据的例子:

    {
      "rep": "market.btcusdt.depth.step0",
      "status": "ok",
      "id": "id10",
      "tick": {
        "bids": [
        [9999.3900,0.0098], // [price, amount]
        [9992.5947,0.0560],
        // more Market Depth data here
        ]
        "asks": [
        [10010.9800,0.0099]
        [10011.3900,2.0000]
        //more data here
        ]
      }
    }
    

    订阅 Trade Detail 数据 market.$symbol.trade.detail

    {
      "sub": "market.$symbol.trade.detail",
      "id": "id generated by client"
    }
    
    参数名称是否必须类型描述默认值取值范围
    symbol true string 交易对   btcusdt, ethusdt, ltcusdt, etcusdt, bchusdt, ethbtc, ltcbtc, etcbtc, bchbtc...

    正确订阅例子:

    {
      "sub": "market.btcusdt.trade.detail",
      "id": "id1"
    }
    

    订阅成功返回数据的例子:

    {
      "id": "id1",
      "status": "ok",
      "subbed": "market.btcusdt.trade.detail",
      "ts": 1489474081631
    }
    

    之后每当 Trade Detail 有更新时,client 会收到数据,例子:

    {
      "ch": "market.btcusdt.trade.detail",
      "ts": 1489474082831,
      "tick": {
            "id": 14650745135,
            "ts": 1533265950234,
            "data": [
                {
                    "amount": 0.0099,
                    "ts": 1533265950234,
                    "id": 146507451359183894799,
                    "price": 401.74,
                    "direction": "buy"
                },
                // more Trade Detail data here
            ]
        }
      
      ]
      }
    }
    

    data 说明:

      "data": [
        {
          "id":        消息ID,
          "price":     成交价,
          "time":      成交时间,
          "amount":    成交量,
          "direction": 成交方向,
          "tradeId":   成交ID,
          "ts":        时间戳
        }
      ]
    

    请求 Trade Detail 数据 market.$symbol.trade.detail

    {
      "req": "market.$symbol.trade.detail",
      "id": "id generated by client"
    }
    
    • 仅能获取最近 300 个 Trade Detail 数据

    请求 Trade Detail 数据的例子

    {
      "req": "market.btcusdt.trade.detail",
      "id": "id11"
    }
    

    返回数据的例子:

    {
      "rep": "market.btcusdt.trade.detail",
      "status": "ok",
      "id": "id11",
      "data": [
        {
          "id":        601595424,
          "price":     10195.64,
          "time":      1494495766,
          "amount":    0.2943,
          "direction": "buy",
          "tradeId":   601595424,
          "ts":        1494495766000
        },
        {
          "id":        601595423,
          "price":     10195.64,
          "time":      1494495711,
          "amount":    0.2430,
          "direction": "buy",
          "tradeId":   601595423,
          "ts":        1494495711000
        },
        // more Trade Detail data here
      ]
    }
    

    请求 Market Detail 数据 market.$symbol.detail

    {
      "req": "market.$symbol.detail",
      "id": "id generated by client"
    }
    
    • 仅返回当前 Market Detail

    请求 Market Detail 数据的例子

    {
      "req": "market.btcusdt.detail",
      "id": "id12"
    }
    

    返回数据的例子:

    {
      "rep": "market.btcusdt.detail",
      "status": "ok",
      "id": "id12",
      "tick": {
        "amount": 12224.2922,
        "open":   9790.52,
        "close":  10195.00,
        "high":   10300.00,
        "ts":     1494496390000,
        "id":     1494496390,
        "count":  15195,
        "low":    9657.00,
        "vol":    121906001.754751
      }
    }

    订阅accounts

    订阅accounts资产变动更新。

    订阅请求数据格式说明

    字段名称类型说明
    op string 必填;操作名称,订阅固定值为 sub;
    cid string 选填;Client 请求唯一 ID
    topic string 必填;订阅主题名称,详细主题列表请参考附录;

    订阅请求示例

    正确的订阅请求

    {
      "op": "sub",
      "cid": "40sG903yz80oDFWr",
      "topic": "accounts"
     
    }
    

    订阅成功返回数据示例

    {
      "op": "sub",
      "cid": "40sG903yz80oDFWr",
      "err-code": 0,
      "ts": 1489474081631,
      "topic": "accounts"
    }
    

    之后每当 Account 有更新时,Client 会收到数据,比如,

    {
      "op": "notify",
      "ts": 1522856623232,
      "topic": "accounts",
      "data": {
        "event": "order.match|order.place|order.refund|order.cancel|order.fee-refund|margin.transfer|margin.loan|margin.interest|margin.repay|other",
        "list": [
          {
            "account-id": 419013,
            "currency": "usdt",
            "type": "trade",
            "balance": "500009195917.4362872650"
          },
          {
            "account-id": 419013,      
            "currency": "btc",
            "type": "frozen",
            "balance": "9786.6783000000"
          }
        ]
      }
    }
    

    Accounts变化通知数据格式说明

    名称类型说明
    event string 资产变化通知相关事件说明,比如订单创建(order.place) 、订单成交(order.match)、订单成交退款(order.refund)、订单撤销(order.cancel) 、点卡抵扣交易手续费(order.fee-refund)、杠杆账户划转(margin.transfer)、借贷本金(margin.loan)、借贷计息(margin.interest)、归还借贷本金利息(margin.repay)、其他资产变化(other)
    account-id long 账户 id
    currency string 币种
    type string 账户类型, 比如交易可用账户(trade),交易冻结账户(frozen)
    balance string 账户余额

    订阅orders.$symbol

    订阅订单更新

    订阅请求数据格式说明

    字段名称类型说明
    op string 必填;操作名称,订阅固定值为 sub;
    cid string 选填;Client 请求唯一 ID
    topic string 必填;订阅主题名称,详细主题列表请参考附录;

    正确的订阅请求

    {
      "op": "sub",
      "cid": "40sG903yz80oDFWr",
      "topic": "orders.htusdt"
     
    }
    

    订阅成功返回数据示例

    {
      "op": "sub",
      "cid": "40sG903yz80oDFWr",
      "err-code": 0,
      "ts": 1489474081631,
      "topic": "orders.htusdt"
    }
    

    之后每当 Order 有更新时,Client 会收到数据,比如,

    {
      "op": "notify",
      "topic": "orders.htusdt",
      "ts": 1522856623232,
      "data": {
        "seq-id": 94984,
        "order-id": 2039498445,
        "symbol": "htusdt",
        "account-id": 100077,
        "order-amount": "5000.000000000000000000",
        "order-price": "1.662100000000000000",
        "created-at": 1522858623622,
        "order-type": "buy-limit",
        "order-source": "api",
        "order-state": "filled",
        "role": "taker|maker",
        "price": "1.662100000000000000",
        "filled-amount": "5000.000000000000000000",
        "unfilled-amount": "0.000000000000000000",
        "filled-cash-amount": "8301.357280000000000000",
        "filled-fees": "8.000000000000000000"
      }
    }
    

    订单变化通知数据格式说明

    名称类型说明
    seq-id long 流水号(不连续)
    order-id long 订单 id
    symbol string 交易对
    account-id long 账户 id
    order-amount string 订单数量
    order-price string 订单价格
    created-at long 订单创建时间
    order-type string 订单类型,请参考订单类型说明
    order-source string 订单来源,请参考订单来源说明
    order-state string 订单状态,请参考订单状态说明
    role string maker, taker
    price string 成交价格
    filled-amount string 单次成交数量
    unfilled-amount string 单次未成交数量
    filled-cash-amount string 单次成交金额
    filled-fees string 单次成交手续费(买入为币,卖出为钱)

    错误订阅请求示例(错误的 topic)

    {
      "op": "sub",
      "topic": "foo.bar",
      "cid": "40sG903yz80oDFWr"
    }
    

    订阅失败会返回下面示例数据

    {
      "op": "sub",
      "topic": "foo.bar",
      "cid": "40sG903yz80oDFWr",
      "err-code": 1001, //具体编码请参考响应码表
      "err-msg": “详细的错误信息”,
      "ts": 1489474081631
    }
    

    取消订阅数据(unsub)

    成功建立和 WebSocket API 的连接之后,向 Server 发送如下格式的数据来取消订阅数据:

    取消订阅请求数据格式

    {
      “op”: “unsub”,
      “topic": "topic to unsub”,
      "cid": "id generated by client”,
    }
    

    取消订阅请求数据格式说明

    字段名称类型说明
    op string 必填;操作名称,订阅固定值为 unsub;
    cid string 选填;Client 请求唯一 ID
    topic string 必填;待取消订阅主题名称,详细主题列表请参考附录;

    取消订阅请求示例

    正确的取消订阅请求

    {
      "op": "unsub",
      "topic": "accounts",
      "cid": "40sG903yz80oDFWr"
    }
    

    取消订阅成功返回数据示例

    {
      "op": "unsub",
      "topic": "accounts",
      "cid": "id generated by client",
      "err-code": 0,
      "ts": 1489474081631
    }
    

    订阅与取消订阅规则说明

    订阅(sub)取消订阅(unsub)规则
    accounts accounts 允许
    orders.* orders.* 允许
    orders.symbol1 orders.* 允许
    orders.symbol1 orders.symbol1 允许
    orders.symbol1 orders.symbol2 不允许
    orders.* orders.symbol1 不允许

    请求用户资产 - accounts.list

    查询当前用户的所有账户余额数据

    成功建立和 WebSocket API 的连接之后,向 Server发送如下格式的数据来查询账户数据:

    账户查询请求数据格式说明

    字段名称类型说明
    op string 必填;操作名称,固定值为 req;
    cid string 选填;Client 请求唯一 ID
    topic string 必填;固定值为accounts.list,详细主题列表请参考附录;

    账户查询请求示例

    请求内容

    {
      "op": "req",
      "topic": "accounts.list",
      "cid": "40sG903yz80oDFWr"
    }
    

    调用成功返回数据

    {
      "op": "req",
      "topic": "accounts.list",
      "cid": "40sG903yz80oDFWr"
      "err-code": 0,
      "ts": 1489474082831,
      "data": [
        {
          "id": 419013,
          "type": "spot",
          "state": "working",
          "list": [
            {
              "currency": "usdt",
              "type": "trade",
              "balance": "500009195917.4362872650"
            },
            {
              "currency": "usdt",
              "type": "frozen",
              "balance": "9786.6783000000"
            }
          ]
        },
        {
          "id": 35535,
          "type": "point",
          "state": "working",
          "list": [
            {
              "currency": "eth",
              "type": "trade",
              "balance": "499999894616.1302471000"
            },
            {
              "currency": "eth",
              "type": "frozen",
              "balance": "9786.6783000000"
            }
          ]
        }
      ]
    }
    

    调用失败应答数据示例

    {
      "op": "req",
      "topic": "foo.bar",
      "cid": "40sG903yz80oDFWr"
      "err-code": 12001, //具体编码需要参考响应码表
      “err-msg": "详细的错误信息”,
      "ts": 1489474081631
    }
    

    请求交易订单 - orders.list

    查询当前委托、历史委托

    成功建立和 WebSocket API 的连接之后,向 Server发送如下格式的数据来查询委托数据:

    订单列表查询请求数据格式
    {
      "op": "req",
      "topic": "orders.list",
      "cid": "40sG903yz80oDFWr",
      "account-id": "$account-id",
      "symbol": "$symbol",
      "types": "$order-type",
      "start-date": "$start-date",
      "end-date": "$end-date",  
      "states": "$order-state",
      "from": "$from",
      "direct": "$direct",
      "size": "$size"
    }
    

    订单查询请求数据格式说明

    参数名称是否必须类型描述默认值取值范围
    op true string 操作名称,固定值为 req    
    cid false string Client 请求唯一 ID    
    topic true string 固定值为 orders.list,详细主题列表请参考附录    
    account-id true long 账户 id    
    symbol true string 交易对   btcusdt, ltcbtc, etcbtc, htusdt......
    types false string 查询的订单类型组合,使用','分割   参考订单类型说明
    start-date false string 查询开始日期, 日期格式yyyy-mm-dd    
    end-date false string 查询结束日期, 日期格式yyyy-mm-dd    
    states true string 查询的订单状态组合,使用','分割    
    from false string 查询起始 ID    
    direct false string 查询方向   prev 向前,next 向后
    size false string 查询记录大小    

    订单列表查询请求示例

    {
      "op": "req",
      "topic": "orders.list",
      "cid": "40sG903yz80oDFWr",
      "symbol": "htusdt",
      "states": "submitted,partial-filled"
    }
    

    调用成功返回数据

    {
      "op": "req",
      "topic": "orders.list",
      "cid": "40sG903yz80oDFWr",
      "err-code": 0,
      "ts": 1522856623232,
      "data": [
        {
          "id": 2039498445,
          "symbol": "htusdt",
          "account-id": 100077,
          "amount": "5000.000000000000000000",
          "price": "1.662100000000000000",
          "created-at": 1522858623622,
          "type": "buy-limit",
          "filled-amount": "5000.000000000000000000",
          "filled-cash-amount": "8301.357280000000000000",
          "filled-fees": "8.000000000000000000",
          "finished-at": 1522858624796,
          "source": "api",
          "state": "filled",
          "canceled-at": 0
        }
      ]
    }
    

    应答数据格式说明,

    名称类型说明
    id long 订单ID
    symbol string 交易对
    account-id long 账户ID
    amount string 订单数量
    price string 订单价格
    created-at long 订单创建时间
    type string 订单类型,请参考订单类型说明
    filled-amount string 已成交数量
    filled-cash-amount string 已成交总金额
    filled-fees string 已成交手续费
    finished-at string 最后成交时间
    source string 订单来源,请参考订单来源说明
    state string 订单状态,请参考订单状态说明
    cancel-at long 撤单时间

    请求某个订单详情 - orders.detail

    查询某个订单详情

    成功建立和 WebSocket API 的连接之后,向 Server发送如下格式的数据来查询某个订单详情数据:

    订单详情查询请求数据格式

    {
      "op": "req",
      "topic": "orders.detail",
      "order-id": "$order-id"
      "cid": "40sG903yz80oDFWr"
    }
    

    订单详情查询请求数据格式说明

    参数名称是否必须类型描述默认值取值范围
    op true string 操作名称,固定值为 req    
    cid true string Client 请求唯一 ID    
    topic false string 固定值为 orders.detail,详细主题列表请参考附录    
    order-id true string 订单ID    
    订单详情查询请求示例

    请求内容

    {
      "op": "req",
      "topic": "orders.detail",
      "order-id": "2039498445"
      "cid": "40sG903yz80oDFWr"
    }
    

    调用成功返回数据示例

    {
      "op": "req",
      "topic": "orders.detail",
      "cid": "40sG903yz80oDFWr"
      "err-code": 0,
      "ts": 1522856623232,
      "data": {
        "id": 2039498445,
        "symbol": "htusdt",
        "account-id": 100077,
        "amount": "5000.000000000000000000",
        "price": "1.662100000000000000",
        "created-at": 1522858623622,
        "type": "buy-limit",
        "filled-amount": "5000.000000000000000000",
        "filled-cash-amount": "8301.357280000000000000",
        "filled-fees": "8.000000000000000000",
        "finished-at": 1522858624796,
        "source": "api",
        "state": "filled",
        "canceled-at": 0
      }
    }
    

    请求数据(req)限流策略

    为鼓励用户使用订阅接收数据推送,对查询请求做了限流策略, 规则如下:

    • accounts.list 查询请求,同一个用户(不论几个连接),每2次请求间隔不能小于25秒(此数字可能发生变化),否则会接收到“too many request"的错误应答。
    • orders.list 和 orders.detail 查询请求,同一个用户(不论几个连接),每2次请求间隔不能小于5秒(此数字可能发生变化),否则会接收到“too many request"的错误应答。

    附录

    操作类型(OP )说明

    类型描述
    ping 心跳发起(server)
    pong 心跳应答
    auth 鉴权
    sub 订阅消息
    unsub 取消订阅消息
    req 请求数据
    notify 推送订阅消息(server)

    主题 (Topic) 类型说明

    类型适用操作类型描述
    accounts sub, unsub 订阅、取消订阅所有资产变更消息
    orders.$symbol sub, unsub 订阅、取消订阅指定交易对的订单变更消息,当 $symbol值为 *时代表订阅所有交易对
    accounts.list req 账户数据请求
    orders.list req 订单列表查询请求
    orders.detail req 订单详情查询请求

    响应码(Err-Code)说明

    具体码表请参照error.json

    订单类型(Order Type)说明

    类型描述
    buy-market 市价买
    sell-market 市价卖
    buy-limit 限价买
    sell-limit 限价卖
    buy-ioc 买入立即执行或撤销
    sell-ioc 卖出立即执行或撤销
    buy-limit-maker 限价买入(只能成为maker)
    Sell-limit-maker 限价卖出(只能成为maker)

    订单状态(Order State)说明

    类型描述
    submitted 已提交
    partial-filled 部分成交
    partial-canceled 部分成交撤销(终态)
    filled 完全成交(终态)
    canceled 已撤销(终态)

    订单来源(Order Source)说明

    类型描述
    spot-web 现货 Web 交易单
    spot-api 现货 Api 交易单
    spot-app 现货 App 交易单
    margin-web 借贷 Web 交易单
    margin-api 借贷 Api 交易单
    margin-app 借贷 App 交易单
    fl-sys 借贷强制平仓单(爆仓单)
    展开全文
  • FastAPI WebSocket 简单演示 下午没事看了看WebSocket,感觉这个听好玩的,比写CRUD有意思。就复制了官网的demo演示看了看。 官方文档 效果

    FastAPI WebSocket 简单演示

    下午没事看了看WebSocket,感觉这个挺好玩的,比写CRUD有意思。就复制了官网的demo演示看了看。

    官方文档 https://fastapi.tiangolo.com/advanced/websockets/

    效果

    简单效果演示

    WebSocket 服务

    使用Python FastAPI框架官网demo

    from typing import List
    
    from fastapi import FastAPI, WebSocket, WebSocketDisconnect
    
    app = FastAPI()
    
    
    class ConnectionManager:
        def __init__(self):
            # 存放激活的ws连接对象
            self.active_connections: List[WebSocket] = []
    
        async def connect(self, ws: WebSocket):
            # 等待连接
            await ws.accept()
            # 存储ws连接对象
            self.active_connections.append(ws)
    
        def disconnect(self, ws: WebSocket):
            # 关闭时 移除ws对象
            self.active_connections.remove(ws)
    
        @staticmethod
        async def send_personal_message(message: str, ws: WebSocket):
            # 发送个人消息
            await ws.send_text(message)
    
        async def broadcast(self, message: str):
            # 广播消息
            for connection in self.active_connections:
                await connection.send_text(message)
    
    
    manager = ConnectionManager()
    
    
    @app.websocket("/ws/{user}")
    async def websocket_endpoint(websocket: WebSocket, user: str):
    
        await manager.connect(websocket)
    
        await manager.broadcast(f"用户{user}进入聊天室")
    
        try:
            while True:
                data = await websocket.receive_text()
                await manager.send_personal_message(f"你说了: {data}", websocket)
                await manager.broadcast(f"用户:{user} 说: {data}")
    
        except WebSocketDisconnect:
            manager.disconnect(websocket)
            await manager.broadcast(f"用户-{user}-离开")
    
    if __name__ == "__main__":
        import uvicorn
        # 官方推荐是用命令后启动 uvicorn main:app --host=127.0.0.1 --port=8010 --reload
        uvicorn.run(app='main:app', host="127.0.0.1", port=8010, reload=True, debug=True)
    

    前端

    前端只是简单使用演示, 没有对连接做鉴权处理。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>聊天1</title>
    </head>
    <body>
    <h1>User1 Chat</h1>
    <form action="" onsubmit="sendMessage(event)">
        <input type="text" id="messageText" autocomplete="off"/>
        <button>Send</button>
    </form>
    <ul id='messages'>
    </ul>
    
    <script>
        var ws = new WebSocket("ws://127.0.0.1:8010/ws/user1");
    
        ws.onmessage = function(event) {
            var messages = document.getElementById('messages')
            var message = document.createElement('li')
            var content = document.createTextNode(event.data)
            message.appendChild(content)
            messages.appendChild(message)
        };
        function sendMessage(event) {
            var input = document.getElementById("messageText")
            ws.send(input.value)
            input.value = ''
            event.preventDefault()
        }
    </script>
    
    </body>
    </html>
    
    

    用户2, 和上面的用户1没什么区别,只是连接WebSocket 参数变化区分,
    其他地方一样,就是url参数变化了。

    <script>
        var ws = new WebSocket("ws://127.0.0.1:8010/ws/user2");
    
        ws.onmessage = function(event) {
            var messages = document.getElementById('messages')
            var message = document.createElement('li')
            var content = document.createTextNode(event.data)
            message.appendChild(content)
            messages.appendChild(message)
        };
        function sendMessage(event) {
            var input = document.getElementById("messageText")
            ws.send(input.value)
            input.value = ''
            event.preventDefault()
        }
    </script>
    
    

    总结

    WebSocket使用还是很简单的,但是封装鉴权,前端断线重连等等操作还是很耗时的。

    展开全文
  • 从Java SE 11开始,JDK包含一个客户端WebSocket API。Javadoc包含一些代码示例,但是您不能立即使用这些示例。在网上搜索“ java websocket client”将主要显示有关旧JSR 352 websocket的示例和指南。设置一切以完成...

    从Java SE 11开始,JDK包含一个客户端WebSocket API。Javadoc包含一些代码示例,但是您不能立即使用这些示例。在网上搜索“ java websocket client”将主要显示有关旧JSR 352 websocket的示例和指南。设置一切以完成工作并不像预期的那样简单,因此我编写了这个小教程。只要适合,我都会在项目中使用vert.x,并且也有一个websocket客户端API。但是可悲的是vert.x websocket客户端有一些缺点,它不适用于重定向尽管我们不使用vert.x websocket客户端,但我们将vert.x用作小型应用程序的基础。够多了,我们开始编码。要构建并连接到Websocket服务器,构建器需要一个侦听器,该侦听器将侦听传入的数据包:class BitfinexListener(val vertx: Vertx) : WebSocket.Listener {override fun onOpen(webSocket: WebSocket?) {super.onOpen(webSocket)LOGGER.info("websocket opened")this.vertx.periodicStream(60000).toObservable().subscribe { i ->val pingTxt = JsonObject().put("event", "ping").put("cid", Random(2020).nextInt()).encode()webSocket?.sendText(pingTxt, true)?.thenRun {-> LOGGER.info("sent ping {}", pingTxt)}}}var parts: MutableList =MutableList(0) { index: Int -> "" }var accumulatedMessage: CompletableFuture =CompletableFuture()override fun onText(webSocket: WebSocket,message: CharSequence?,last: Boolean): CompletionStage? {parts.add(message)webSocket.request(1)if (last) {val completeMessage = parts.joinToString(separator = ""){ charSequence -> charSequence ?: "" }parts.clear()accumulatedMessage.complete(null)val cf: CompletionStage = accumulatedMessageaccumulatedMessage = CompletableFuture()onMessage(completeMessage)return cf}return accumulatedMessage}fun onMessage(message: String) {val bitfinexMessage = Json.decodeValue(message)// ... see repo at github for full code}}我们重写onOpen方法以建立对bitfinex的定期ping。重要的一件事是,当您覆盖onOpen时,必须调用super.onOpen,否则客户端不会向服务器发送任何数据。我花了很多时间才发现这个错误。由于侦听器是一个接口,所以我不习惯于调用接口的超级方法。但在这种情况下这很重要。java8中引入的接口中默认方法的概念对我来说还没有成为第二天性。onText消息将收集所有传输的文本数据,直到文本完成为止(通常是一次调用inText的情况)。文本完成后,将通过onMessage方法中的vert.x事件总线发送文本。现在,我们可以使用此侦听器设置一个表示与bitfinex的连接的顶点:class BitfinexConnection : AbstractVerticle() {var webSocket: WebSocket? = nulloverride fun start() {LOGGER.info("deploying BitfinexConnection")val subs = vertx.sharedData().getLocalMap("bitfinex.subscriptions")val listener = BitfinexListener(this.vertx, subs)val client = HttpClient.newHttpClient()val uri = URI.create("wss://api-pub.bitfinex.com/ws/2")this.webSocket = client.newWebSocketBuilder().buildAsync(uri), listener).join()vertx.eventBus().consumerif ( webSocket==null || webSocket?.isOutputClosed()!!) {jsonMsg.reply(JsonObject().put("message", "websocket closed").put("StatusCode",503))return@handler}val bitfinexMessage = jsonMsg.body().encode()this.webSocket?.sendText(bitfinexMessage,true)?.thenRun{ LOGGER.debug("delivered {} ", bitfinexMessage)}}}}该类非常简单明了,在verticle的start方法中,将初始化并启动与公共bitfinex api的websocket连接。应通过vert.x事件总线将消息直接发送到websocket,因此我们在地址BITFINEX_EB_ADDRESS上启动使用者。在最后一步,我们将所有内容放在一起,并尝试订阅tBTCUSD代码:fun main() {val vertx = Vertx.vertx()val symbol = "tBTCUSD"vertx.rxDeployVerticle(BitfinexConnection::class.java.name).subscribe({ id ->LOGGER.info("deployed bitfinex connection {}", id)val address = "ticker." + symbolvertx.eventBus().consumer(address).handler { jsonMsg ->LOGGER.info("received {} {}", address,jsonMsg.body().encodePrettily())}val subscribeMessage = JsonObject().bfxSubscribeTickerMessage(symbol)vertx.eventBus().send(BITFINEX_EB_ADDRESS, subscribeMessage)},{ t: Throwable? ->LOGGER.error("deployment failed", t) })}main方法启动Vertx并部署bitfinex Websocket Verticle。部署完成后,我们将带有订阅有效负载的消息发送到websocket verticle,并在特殊的eventbus地址上启动使用者。您可以在github上找到所有代码,对其进行克隆,以确保已安装Java 11或更高版本,并使用以下命令运行它:./gradlew run我希望本教程将为您快速启动项目中的websocket客户端代码。

    展开全文
  • 币安Binance API Websocket

    千次阅读 2018-11-08 18:19:00
    本文介绍币安Binance API Websocket General WSS information The base endpoint is:wss://stream.binance.com:9443 Streams can be access either in a single raw stream or a combined stream Raw streams are....
  • FastAPI WebSocket

    2020-10-20 17:30:42
    首先安装 websockets , 别...from fastapi import FastAPI, WebSocket, WebSocketDisconnect fastAPI 中的WebSocket也是基于websockets运行的 不安装websockets 前端报错:failed: Error during WebSocket handsha
  • c# webapi websocket 服务端消息发送 WebSocketForWebAPI:https://gitee.com/lycz/WebSocketForWebAPI 服务端发送消息,控制器代码 private readonly ClientWebSocket webSocket = new ClientWebSocket(); ...
  • C++ API WebSocket example

    2020-11-27 03:39:18
    The first one adds an API function to determine whether a transaction is a websocket request and adds code to the InterceptPlugin to make it behave appropriately. The second one provides a working ...
  • 基于vs 2013 c# MVC API 使用websocket 的测试通过,代码简单,应该方便。。
  • FastAPI WebSocket 分组发送Json数据 用户1和 用户2 可以互相发送私信消息 用户1 2 3之间相当于一个群,可以发送广播消息 效果 代码 FastAPI 服务端代码 #!/usr/bin/env python # -*- coding: utf-8 -*- # @...
  • <div><p>Implements a simple WebSocket echo server as a C++ API InterceptPlugin.</p><p>该提问来源于开源项目:apache/trafficserver</p></div>
  • namespace WebApiDemo.Controllers { public class SocketController : ApiController { //websocket列表,用于记录在线websocket链接 private static List<UserWebSocket> webSockets = new List(); [HttpGet] ...
  • t seem to work for the Bria softphone desktop API after their 5.8 update. The socket connection establishes without any issues but when I write to it, it doesn't seem to transfer. When I try to ...
  • OKEX API(Websocket)

    2018-11-08 17:43:00
    本文介绍OKEX API Websocket WebSocket API for SPOT 开始使用 WebSocket是HTML5一种新的协议(Protocol)。它实现了客户端与服务器全双工通信,使得数据可以快速地双向传播。通过一次简单的握手就可以建立...
  • Java WebSocket 实践2 - 基于Spring 低层级WebSocket API 实现WebSocket 基于Spring 低层级WebSocket API 实现WebSocket 基于Spring 低层级实现一个WebSoket Demo 不基于注解,而是需要用到一些Spring 提供的接口和...
  • 对于一个小型加密项目,我想使用Bitfinex WebSocket API实时获取市场数据。从Java SE 11开始,JDK包含一个客户端WebSocket API。Javadoc包含一些代码示例,但是您不能立即使用这些示例。在网上搜索“ java websocket...
  • poloniex-api-node是Poloniex REST和WebSocket API的简单node.js包装器。 REST API支持回调和Promise。 公共订单簿和您的私人帐户也支持WebSocket API。 内容 建设者 REST API WebSocket API 变更日志 查看详细...
  • REST APIWebSocket API区别

    千次阅读 2019-03-19 18:25:19
    交易所一般都会提供这两种类型的API. REST API:向服务器请求数据,然后...WebSocket API:与服务器建立一个连接,服务器上数据有任何变动,会实时推送到终端,便于高频操作。 . . . 2019-03-19 18:24:54写于上海 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,264
精华内容 3,305
关键字:

apiwebsocket