Skip to content

Commit f059642

Browse files
committed
perf: 完善文档
1 parent 93e66ac commit f059642

18 files changed

Lines changed: 4564 additions & 2 deletions

File tree

Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/MvcHandler/MvcChannelHandler.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,6 @@ private async Task MvcForward(HttpContext context, WebSocket webSocket, WebSocke
319319

320320
}
321321

322-
// Feature 要做流量控制 🔨🔨🔨
323-
324322
// 执行BeforeReceivingData管道
325323
_ = await InvokePipeline(RequestPipelineStage.BeforeReceivingData, context, webSocket, null, null);
326324

Cyaim.WebSocketServer/Sample/Cyaim.WebSocketServer.Sample.Dashboard/Program.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@
7575
// Add HTTP client for test API / 为测试 API 添加 HTTP 客户端
7676
builder.Services.AddHttpClient();
7777

78+
// Add CORS support for testing / 添加 CORS 支持用于测试
79+
builder.Services.AddCors(options =>
80+
{
81+
options.AddPolicy("AllowAll", policy =>
82+
{
83+
policy.AllowAnyOrigin()
84+
.AllowAnyMethod()
85+
.AllowAnyHeader();
86+
});
87+
});
88+
7889
// Register WebSocket Cluster Test API / 注册 WebSocket 集群测试 API
7990
builder.Services.AddSingleton<IWebSocketClusterTestApi>(provider =>
8091
{
@@ -134,6 +145,9 @@
134145
});
135146
}
136147

148+
// Enable CORS / 启用 CORS
149+
app.UseCors("AllowAll");
150+
137151
app.UseRouting();
138152

139153
app.UseEndpoints(endpoints =>
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
# 客户端消息发送测试指南 / Client Message Sending Test Guide
2+
3+
## 测试步骤 / Test Steps
4+
5+
### 1. 启动集群节点 / Start Cluster Nodes
6+
7+
启动至少 2 个节点(例如 node1 和 node2)
8+
9+
### 2. 建立 WebSocket 连接 / Establish WebSocket Connections
10+
11+
#### Client1 连接(连接到 node1)
12+
```javascript
13+
// 在浏览器控制台或 Node.js 中执行
14+
const ws1 = new WebSocket('ws://localhost:5001/ws');
15+
ws1.onopen = () => {
16+
console.log('Client1 connected, ConnectionId:', ws1.url);
17+
};
18+
ws1.onmessage = (event) => {
19+
console.log('Client1 received:', event.data);
20+
};
21+
```
22+
23+
#### Client2 连接(连接到 node2)
24+
```javascript
25+
const ws2 = new WebSocket('ws://localhost:5002/ws');
26+
ws2.onopen = () => {
27+
console.log('Client2 connected');
28+
};
29+
ws2.onmessage = (event) => {
30+
console.log('Client2 received:', event.data);
31+
};
32+
```
33+
34+
### 3. 获取连接 ID / Get Connection IDs
35+
36+
#### 方法 1: 通过 API 查询 / Method 1: Query via API
37+
38+
```bash
39+
# 获取所有连接
40+
curl http://localhost:5001/ws_server/api/client
41+
42+
# 获取 node1 的连接
43+
curl http://localhost:5001/ws_server/api/client?nodeId=node1
44+
45+
# 获取 node2 的连接
46+
curl http://localhost:5002/ws_server/api/client?nodeId=node2
47+
```
48+
49+
#### 方法 2: 从 WebSocket 对象获取 / Method 2: Get from WebSocket object
50+
51+
注意:浏览器 WebSocket API 不直接提供 ConnectionId,需要通过服务器日志或 API 查询获取。
52+
53+
### 4. 发送消息 / Send Message
54+
55+
#### 使用 curl 命令 / Using curl
56+
57+
```bash
58+
# Client1 发送消息给 Client2
59+
# 假设 Client2 的 ConnectionId 是 "0HNHDGIF4BNLV"
60+
61+
curl -X POST http://localhost:5001/ws_server/api/messages/send \
62+
-H "Content-Type: application/json" \
63+
-d '{
64+
"connectionId": "0HNHDGIF4BNLV",
65+
"content": "Hello from Client1!",
66+
"messageType": "Text"
67+
}'
68+
```
69+
70+
#### 使用 PowerShell / Using PowerShell
71+
72+
```powershell
73+
# Client1 发送消息给 Client2
74+
$body = @{
75+
connectionId = "0HNHDGIF4BNLV"
76+
content = "Hello from Client1!"
77+
messageType = "Text"
78+
} | ConvertTo-Json
79+
80+
Invoke-RestMethod -Uri "http://localhost:5001/ws_server/api/messages/send" `
81+
-Method POST `
82+
-ContentType "application/json" `
83+
-Body $body
84+
```
85+
86+
#### 使用 Swagger UI / Using Swagger UI
87+
88+
1. 打开 `http://localhost:5001/swagger`
89+
2. 找到 `/ws_server/api/messages/send` 接口
90+
3. 点击 "Try it out"
91+
4. 输入参数:
92+
- `connectionId`: Client2 的连接 ID
93+
- `content`: 消息内容
94+
- `messageType`: "Text" 或 "Binary"
95+
5. 点击 "Execute"
96+
97+
### 5. 验证消息接收 / Verify Message Reception
98+
99+
检查 Client2 的 WebSocket 是否收到消息:
100+
101+
```javascript
102+
// 在 Client2 的浏览器控制台中
103+
ws2.onmessage = (event) => {
104+
console.log('Client2 received message:', event.data);
105+
alert('Received: ' + event.data);
106+
};
107+
```
108+
109+
## 测试场景 / Test Scenarios
110+
111+
### 场景 1: 同节点内消息发送 / Scenario 1: Same Node Message Sending
112+
- Client1 和 Client2 都连接到 node1
113+
- 从 node1 发送消息给 Client2
114+
115+
### 场景 2: 跨节点消息发送 / Scenario 2: Cross-Node Message Sending
116+
- Client1 连接到 node1
117+
- Client2 连接到 node2
118+
- 从 node1 发送消息给 Client2(通过集群路由)
119+
120+
### 场景 3: 广播消息 / Scenario 3: Broadcast Message
121+
122+
```bash
123+
# 广播消息给所有连接
124+
curl -X POST http://localhost:5001/ws_server/api/messages/broadcast \
125+
-H "Content-Type: application/json" \
126+
-d '{
127+
"content": "Broadcast message to all clients!",
128+
"messageType": "Text"
129+
}'
130+
```
131+
132+
## 完整测试脚本 / Complete Test Script
133+
134+
### HTML 测试页面 / HTML Test Page
135+
136+
创建一个 `test-client-message.html` 文件:
137+
138+
```html
139+
<!DOCTYPE html>
140+
<html>
141+
<head>
142+
<title>WebSocket Client Message Test</title>
143+
</head>
144+
<body>
145+
<h1>WebSocket 客户端消息测试</h1>
146+
147+
<div>
148+
<h2>Client1 (连接到 node1)</h2>
149+
<button onclick="connectClient1()">连接 Client1</button>
150+
<button onclick="disconnectClient1()">断开 Client1</button>
151+
<div id="client1-status">未连接</div>
152+
<div id="client1-messages"></div>
153+
</div>
154+
155+
<div>
156+
<h2>Client2 (连接到 node2)</h2>
157+
<button onclick="connectClient2()">连接 Client2</button>
158+
<button onclick="disconnectClient2()">断开 Client2</button>
159+
<div id="client2-status">未连接</div>
160+
<div id="client2-messages"></div>
161+
</div>
162+
163+
<div>
164+
<h2>发送消息</h2>
165+
<input type="text" id="target-connection-id" placeholder="目标连接ID">
166+
<input type="text" id="message-content" placeholder="消息内容">
167+
<button onclick="sendMessage()">发送消息</button>
168+
</div>
169+
170+
<script>
171+
let ws1 = null;
172+
let ws2 = null;
173+
let client1Id = null;
174+
let client2Id = null;
175+
176+
function connectClient1() {
177+
ws1 = new WebSocket('ws://localhost:5001/ws');
178+
ws1.onopen = () => {
179+
document.getElementById('client1-status').textContent = '已连接';
180+
fetchClientIds();
181+
};
182+
ws1.onmessage = (event) => {
183+
const div = document.getElementById('client1-messages');
184+
div.innerHTML += '<p>收到: ' + event.data + '</p>';
185+
};
186+
ws1.onerror = (error) => {
187+
console.error('Client1 error:', error);
188+
};
189+
}
190+
191+
function connectClient2() {
192+
ws2 = new WebSocket('ws://localhost:5002/ws');
193+
ws2.onopen = () => {
194+
document.getElementById('client2-status').textContent = '已连接';
195+
fetchClientIds();
196+
};
197+
ws2.onmessage = (event) => {
198+
const div = document.getElementById('client2-messages');
199+
div.innerHTML += '<p>收到: ' + event.data + '</p>';
200+
};
201+
ws2.onerror = (error) => {
202+
console.error('Client2 error:', error);
203+
};
204+
}
205+
206+
function disconnectClient1() {
207+
if (ws1) {
208+
ws1.close();
209+
ws1 = null;
210+
document.getElementById('client1-status').textContent = '已断开';
211+
}
212+
}
213+
214+
function disconnectClient2() {
215+
if (ws2) {
216+
ws2.close();
217+
ws2 = null;
218+
document.getElementById('client2-status').textContent = '已断开';
219+
}
220+
}
221+
222+
async function fetchClientIds() {
223+
try {
224+
const response = await fetch('http://localhost:5001/ws_server/api/client');
225+
const data = await response.json();
226+
if (data.success && data.data) {
227+
// 假设第一个连接是 Client1,第二个是 Client2
228+
if (data.data.length > 0) {
229+
client1Id = data.data[0].connectionId;
230+
document.getElementById('target-connection-id').placeholder = '当前可用: ' + client1Id;
231+
}
232+
if (data.data.length > 1) {
233+
client2Id = data.data[1].connectionId;
234+
}
235+
}
236+
} catch (error) {
237+
console.error('Failed to fetch client IDs:', error);
238+
}
239+
}
240+
241+
async function sendMessage() {
242+
const connectionId = document.getElementById('target-connection-id').value || client2Id;
243+
const content = document.getElementById('message-content').value;
244+
245+
if (!connectionId || !content) {
246+
alert('请填写连接ID和消息内容');
247+
return;
248+
}
249+
250+
try {
251+
const response = await fetch('http://localhost:5001/ws_server/api/messages/send', {
252+
method: 'POST',
253+
headers: {
254+
'Content-Type': 'application/json'
255+
},
256+
body: JSON.stringify({
257+
connectionId: connectionId,
258+
content: content,
259+
messageType: 'Text'
260+
})
261+
});
262+
263+
const result = await response.json();
264+
if (result.success) {
265+
alert('消息发送成功!');
266+
} else {
267+
alert('消息发送失败: ' + result.error);
268+
}
269+
} catch (error) {
270+
console.error('Error sending message:', error);
271+
alert('发送消息时出错: ' + error.message);
272+
}
273+
}
274+
</script>
275+
</body>
276+
</html>
277+
```
278+
279+
## 注意事项 / Notes
280+
281+
1. **连接 ID 获取**:连接建立后,需要通过 API 查询获取 ConnectionId
282+
2. **跨节点路由**:如果 Client1 和 Client2 在不同节点,消息会自动通过集群路由
283+
3. **消息格式**:当前发送的是纯文本消息,如果需要发送 JSON,需要在 content 中包含 JSON 字符串
284+
4. **错误处理**:如果连接不存在或已断开,API 会返回相应的错误信息
285+

0 commit comments

Comments
 (0)