TCP 协议
GoSpeedTest TCP 原生协议说明。
概述
TCP 协议提供更高性能的测速能力,适合高带宽网络环境。
- 端口: 12306 (默认)
- 协议: 原生 TCP
- 数据块大小: 4MB
协议格式
消息结构
所有消息都使用以下格式:
[Type (1 byte)][Length (4 bytes, big-endian)][Payload]消息类型
| 类型 | 值 | 说明 |
|---|---|---|
| PING | 0x01 | Ping 测试 |
| DOWNLOAD | 0x02 | 下载测试 |
| UPLOAD | 0x03 | 上传测试 |
| PONG | 0x81 | Ping 响应 |
| DATA | 0x82 | 数据块 |
| RESULT | 0x83 | 测试结果 |
| ERROR | 0xFF | 错误 |
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();
});最佳实践
- 使用连接池:重用 TCP 连接
- 批量发送:使用 4MB 数据块
- 超时处理:设置合理的超时时间
- 错误重试:实现重试机制
- 流量控制:避免网络拥塞
注意事项
- 确保防火墙允许 TCP 12306 端口
- 高带宽网络下推荐使用基于时间的测试
- 数据块大小固定为 4MB
- 所有数值使用大端序(big-endian)