Skip to content

TCP 协议

GoSpeedTest TCP 原生协议说明。

概述

TCP 协议提供更高性能的测速能力,适合高带宽网络环境。

  • 端口: 12306 (默认)
  • 协议: 原生 TCP
  • 数据块大小: 4MB

协议格式

消息结构

所有消息都使用以下格式:

[Type (1 byte)][Length (4 bytes, big-endian)][Payload]

消息类型

类型说明
PING0x01Ping 测试
DOWNLOAD0x02下载测试
UPLOAD0x03上传测试
PONG0x81Ping 响应
DATA0x82数据块
RESULT0x83测试结果
ERROR0xFF错误

Ping 测试

客户端请求

Type: 0x01 (PING)
Length: 0
Payload: (empty)

服务器响应

Type: 0x81 (PONG)
Length: 8
Payload: [Timestamp (8 bytes, big-endian)]

下载测试

客户端请求

Type: 0x02 (DOWNLOAD)
Length: 8
Payload: [Size (8 bytes, big-endian)]

服务器响应

服务器发送多个 DATA 消息:

Type: 0x82 (DATA)
Length: 4194304 (4MB)
Payload: [4MB 随机数据]

最后发送 RESULT 消息:

Type: 0x83 (RESULT)
Length: 24
Payload: [Bytes (8 bytes)][Duration (8 bytes)][SpeedMbps (8 bytes)]

上传测试

客户端请求

Type: 0x03 (UPLOAD)
Length: 8 or 16
Payload: 
  - 基于大小: [Size (8 bytes)]
  - 基于时间: [Size (8 bytes)][Duration (8 bytes)]

客户端发送数据

客户端发送多个 DATA 消息:

Type: 0x82 (DATA)
Length: 4194304 (4MB)
Payload: [4MB 数据]

服务器响应

Type: 0x83 (RESULT)
Length: 24
Payload: [Bytes (8 bytes)][Duration (8 bytes)][SpeedMbps (8 bytes)]

错误处理

错误消息

Type: 0xFF (ERROR)
Length: N
Payload: [Error message (UTF-8 string)]

使用示例

Go 语言示例

go
package main

import (
    "encoding/binary"
    "net"
    "time"
)

const (
    MsgPing     = 0x01
    MsgPong     = 0x81
    MsgDownload = 0x02
    MsgUpload   = 0x03
    MsgData     = 0x82
    MsgResult   = 0x83
    MsgError    = 0xFF
)

func main() {
    conn, err := net.Dial("tcp", "localhost:12306")
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    // Ping 测试
    err = binary.Write(conn, binary.BigEndian, byte(MsgPing))
    if err != nil {
        panic(err)
    }
    err = binary.Write(conn, binary.BigEndian, uint32(0))
    if err != nil {
        panic(err)
    }

    // 读取响应
    var msgType byte
    err = binary.Read(conn, binary.BigEndian, &msgType)
    if err != nil {
        panic(err)
    }
    if msgType == MsgPong {
        println("Ping successful")
    }
}

Python 示例

python
import socket
import struct

MSG_PING = 0x01
MSG_PONG = 0x81
MSG_DOWNLOAD = 0x02
MSG_UPLOAD = 0x03
MSG_DATA = 0x82
MSG_RESULT = 0x83
MSG_ERROR = 0xFF

def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('localhost', 12306))
    
    # Ping 测试
    sock.sendall(struct.pack('B', MSG_PING))
    sock.sendall(struct.pack('>I', 0))
    
    # 读取响应
    msg_type = struct.unpack('B', sock.recv(1))[0]
    if msg_type == MSG_PONG:
        print("Ping successful")
    
    sock.close()

if __name__ == '__main__':
    main()

Node.js 示例

javascript
const net = require('net');

const MSG_PING = 0x01;
const MSG_PONG = 0x81;
const MSG_DOWNLOAD = 0x02;
const MSG_UPLOAD = 0x03;
const MSG_DATA = 0x82;
const MSG_RESULT = 0x83;
const MSG_ERROR = 0xFF;

const client = net.connect(12306, 'localhost', () => {
    // Ping 测试
    const header = Buffer.alloc(5);
    header.writeUInt8(MSG_PING, 0);
    header.writeUInt32BE(0, 1);
    client.write(header);
});

client.on('data', (data) => {
    const msgType = data.readUInt8(0);
    if (msgType === MSG_PONG) {
        console.log('Ping successful');
    }
    client.end();
});

最佳实践

  1. 使用连接池:重用 TCP 连接
  2. 批量发送:使用 4MB 数据块
  3. 超时处理:设置合理的超时时间
  4. 错误重试:实现重试机制
  5. 流量控制:避免网络拥塞

注意事项

  • 确保防火墙允许 TCP 12306 端口
  • 高带宽网络下推荐使用基于时间的测试
  • 数据块大小固定为 4MB
  • 所有数值使用大端序(big-endian)

基于 LGPL-3.0 许可证发布