From d8a9b76a6bb2824c1e9fb0d17938c926472dd78b Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期二, 03 二月 2026 13:44:27 +0800
Subject: [PATCH] 支持帧消息协议并改进 TCP 服务器
---
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Clients.cs | 54 +++++++
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs | 41 +++++
.gitignore | 5
Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json | 88 ++++++++---
项目资料/设备协议/拘束机对接协议/插拔钉机对接协议.xlsx | 0
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json | 18 +-
Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/CodeChunks.db | 0
Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/SemanticSymbols.db | 0
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Dispose.cs | 5
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs | 62 ++++++++
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketServerOptions.cs | 12 +
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs | 131 +++++++++++++++++-
12 files changed, 367 insertions(+), 49 deletions(-)
diff --git a/.gitignore b/.gitignore
index 5f351a2..1a864b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -405,3 +405,8 @@
/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/copilot-chat
/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices
/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices
+/Code/WCS/WIDESEAWCS_Server/.vs
+/Code/WCS/WIDESEAWCS_Server/.vs
+*.db
+Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/CodeChunks.db
+Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/SemanticSymbols.db
diff --git a/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/CodeChunks.db b/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/CodeChunks.db
index 60ffaa7..553d31c 100644
--- a/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/CodeChunks.db
+++ b/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/CodeChunks.db
Binary files differ
diff --git a/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/SemanticSymbols.db b/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/SemanticSymbols.db
index 3118942..dc27659 100644
--- a/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/SemanticSymbols.db
+++ b/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/18.0.988.22099/SemanticSymbols.db
Binary files differ
diff --git a/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json b/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json
index 9aa49c8..8a8146c 100644
--- a/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json
+++ b/Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json
@@ -3,24 +3,32 @@
"WorkspaceRootPath": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\",
"Documents": [
{
- "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
- "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
- },
- {
"AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\tcpsocketserver.messaging.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\tcpsocketserver.messaging.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
- "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\tcpsocketserver.server.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
- "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\tcpsocketserver.server.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\socketserveroptions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\socketserveroptions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\tcpsocketserver.clients.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\tcpsocketserver.clients.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}|WIDESEAWCS_Server\\WIDESEAWCS_Server.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_server\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}",
+ "RelativeMoniker": "D:0:0:{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}|WIDESEAWCS_Server\\WIDESEAWCS_Server.csproj|solutionrelative:wideseawcs_server\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}"
},
{
"AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\tcpsocketserver.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\tcpsocketserver.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
- "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\tcpsocketserver.clients.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
- "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\tcpsocketserver.clients.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\socketserver\\tcpsocketserver.server.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\socketserver\\tcpsocketserver.server.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{83F18A31-5983-4587-A0B2-414BF70E50B5}|WIDESEAWCS_TaskInfoService\\WIDESEAWCS_TaskInfoService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_taskinfoservice\\taskservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
@@ -62,7 +70,7 @@
"DocumentGroups": [
{
"DockedWidth": 200,
- "SelectedChildIndex": 11,
+ "SelectedChildIndex": 14,
"Children": [
{
"$type": "Bookmark",
@@ -78,7 +86,33 @@
},
{
"$type": "Document",
- "DocumentIndex": 8,
+ "DocumentIndex": 1,
+ "Title": "SocketServerOptions.cs",
+ "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\SocketServerOptions.cs",
+ "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\SocketServer\\SocketServerOptions.cs",
+ "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\SocketServerOptions.cs",
+ "RelativeToolTip": "WIDESEAWCS_Tasks\\SocketServer\\SocketServerOptions.cs",
+ "ViewState": "AgIAACEAAAAAAAAAAAAQwCAAAAA7AAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2026-02-03T03:20:50.458Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 4,
+ "Title": "appsettings.json",
+ "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\appsettings.json",
+ "RelativeDocumentMoniker": "WIDESEAWCS_Server\\appsettings.json",
+ "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\appsettings.json",
+ "RelativeToolTip": "WIDESEAWCS_Server\\appsettings.json",
+ "ViewState": "AgIAABUAAAAAAAAAAAAAADYAAAAbAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
+ "WhenOpened": "2026-02-03T03:54:20.54Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 10,
"Title": "TaskTypeEnum.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\TaskEnum\\TaskTypeEnum.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Common\\TaskEnum\\TaskTypeEnum.cs",
@@ -90,7 +124,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 7,
+ "DocumentIndex": 9,
"Title": "TaskEnumHelper.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\TaskEnum\\TaskEnumHelper.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Common\\TaskEnum\\TaskEnumHelper.cs",
@@ -102,7 +136,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 5,
+ "DocumentIndex": 7,
"Title": "TaskService.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_TaskInfoService\\TaskService.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_TaskInfoService\\TaskService.cs",
@@ -114,7 +148,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 11,
+ "DocumentIndex": 13,
"Title": "FormationCommonStackerCraneJob.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\FormationStackerCraneJob\\FormationCommonStackerCraneJob.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\FormationStackerCraneJob\\FormationCommonStackerCraneJob.cs",
@@ -126,7 +160,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 10,
+ "DocumentIndex": 12,
"Title": "ITaskService.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_ITaskInfoService\\ITaskService.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_ITaskInfoService\\ITaskService.cs",
@@ -138,7 +172,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 6,
+ "DocumentIndex": 8,
"Title": "TaskStatusEnum.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\TaskEnum\\TaskStatusEnum.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Common\\TaskEnum\\TaskStatusEnum.cs",
@@ -150,7 +184,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 9,
+ "DocumentIndex": 11,
"Title": "CommonStackerCraneJob.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\StackerCraneJob\\CommonStackerCraneJob.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\StackerCraneJob\\CommonStackerCraneJob.cs",
@@ -163,7 +197,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 12,
+ "DocumentIndex": 14,
"Title": "QuartzNetExtension.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_QuartzJob\\QuartzNet\\QuartzNetExtension.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_QuartzJob\\QuartzNet\\QuartzNetExtension.cs",
@@ -175,65 +209,65 @@
},
{
"$type": "Document",
- "DocumentIndex": 0,
+ "DocumentIndex": 3,
"Title": "RobotJob.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
"ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
"RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
- "ViewState": "AgIAACMAAAAAAAAAAAAAwD4AAABRAAAAAAAAAA==",
+ "ViewState": "AgIAAFYAAAAAAAAAAAAAAGwAAAAMAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-02-02T03:52:06.502Z",
"EditorCaption": ""
},
{
"$type": "Document",
- "DocumentIndex": 1,
+ "DocumentIndex": 0,
"Title": "TcpSocketServer.Messaging.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Messaging.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Messaging.cs",
"ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Messaging.cs",
"RelativeToolTip": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Messaging.cs",
- "ViewState": "AgIAACMAAAAAAAAAAAAkwD4AAAAQAAAAAAAAAA==",
+ "ViewState": "AgIAALYAAAAAAAAAAAAIwLsAAAAWAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-02-02T03:38:35.325Z",
"EditorCaption": ""
},
{
"$type": "Document",
- "DocumentIndex": 3,
+ "DocumentIndex": 5,
"Title": "TcpSocketServer.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.cs",
"ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.cs",
"RelativeToolTip": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.cs",
- "ViewState": "AgIAACQAAAAAAAAAAAAowDYAAAA/AAAAAAAAAA==",
+ "ViewState": "AgIAAB8AAAAAAAAAAAAmwDsAAABaAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-02-02T03:37:56.495Z",
"EditorCaption": ""
},
{
"$type": "Document",
- "DocumentIndex": 4,
+ "DocumentIndex": 2,
"Title": "TcpSocketServer.Clients.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Clients.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Clients.cs",
"ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Clients.cs",
"RelativeToolTip": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Clients.cs",
- "ViewState": "AgIAAAAAAAAAAAAAAAAAAE0AAAAhAAAAAAAAAA==",
+ "ViewState": "AgIAAEQAAAAAAAAAAAAkwGAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-02-02T03:37:53.636Z",
"EditorCaption": ""
},
{
"$type": "Document",
- "DocumentIndex": 2,
+ "DocumentIndex": 6,
"Title": "TcpSocketServer.Server.cs",
"DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Server.cs",
"RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Server.cs",
"ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Server.cs",
"RelativeToolTip": "WIDESEAWCS_Tasks\\SocketServer\\TcpSocketServer.Server.cs",
- "ViewState": "AgIAAFMAAAAAAAAAAAAQwGwAAAAAAAAAAAAAAA==",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAGwAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-02-02T03:37:49.526Z",
"EditorCaption": ""
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
index dac24a5..a6fcc1f 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
@@ -46,14 +46,14 @@
"WebSocketEnable": true, //鏄惁寮�鍚疻ebSocket鏈嶅姟
"WebSocketPort": 9296, //WebSocket鏈嶅姟绔彛
"SocketServer": {
- "Enabled": true,
- "Port": 2000,
- "IpAddress": "0.0.0.0",
- "Backlog": 100,
- "EncodingName": "utf-8",
- "AutoDetectEncoding": true,
- "IdleTimeoutSeconds": 300,
- "EnableHeartbeat": true,
- "LogFilePath": "socketserver.log"
+ "Enabled": true, //鏄惁鍚敤Socket鏈嶅姟鍣�
+ "Port": 2000, //鐩戝惉绔彛
+ "IpAddress": "0.0.0.0", //鐩戝惉鍦板潃锛�
+ "Backlog": 1000, //鏈�澶ц繛鎺ユ暟
+ "EncodingName": "utf-8", //缂栫爜鏂瑰紡
+ "AutoDetectEncoding": true, //鏄惁鑷姩妫�娴嬬紪鐮�
+ "IdleTimeoutSeconds": 300, //绌洪棽瓒呮椂鏃堕棿锛屽崟浣嶇锛�0琛ㄧず涓嶈秴鏃�
+ "EnableHeartbeat": true, //鏄惁鍚敤蹇冭烦妫�娴�
+ "LogFilePath": "socketserver.log" //鏃ュ織鏂囦欢璺緞
}
}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketServerOptions.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketServerOptions.cs
index 718497a..2844c0c 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketServerOptions.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/SocketServerOptions.cs
@@ -25,7 +25,7 @@
/// <summary>
/// 连接队列长度
/// </summary>
- public int Backlog { get; set; } = 100;
+ public int Backlog { get; set; } = 1000;
/// <summary>
/// 文本编码名称(例如: utf-8, gbk)
@@ -51,5 +51,15 @@
/// 日志文件路径(相对于程序运行目录)
/// </summary>
public string LogFilePath { get; set; } = "socketserver.log";
+
+ /// <summary>
+ /// 消息头标记
+ /// </summary>
+ public string MessageHeader { get; set; } = "<START>";
+
+ /// <summary>
+ /// 消息尾标记
+ /// </summary>
+ public string MessageFooter { get; set; } = "<END>";
}
}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Clients.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Clients.cs
index 9654ae2..f59a31e 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Clients.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Clients.cs
@@ -9,6 +9,11 @@
{
public partial class TcpSocketServer
{
+ /// <summary>
+ /// 检索当前在服务中注册的所有客户端标识符的只读列表。
+ /// </summary>
+ /// <remarks>返回的列表表示调用时刻客户端ID的快照。后续对客户端集合的更改不会影响返回的列表。此方法是线程安全的。</remarks>
+ /// <returns>包含客户端ID的<see cref="IReadOnlyList{String}"/>。如果没有客户端注册,列表将为空。</returns>
public IReadOnlyList<string> GetClientIds()
{
lock (_syncRoot)
@@ -17,6 +22,12 @@
}
}
+ /// <summary>
+ /// 检索与指定设备标识符关联的客户端标识符。
+ /// </summary>
+ /// <remarks>此方法是线程安全的。如果未找到设备标识符,方法将返回null而不是抛出异常。</remarks>
+ /// <param name="deviceId">要检索客户端标识符的设备的唯一标识符。不能为null。</param>
+ /// <returns>与指定设备标识符关联的客户端标识符,如果不存在关联则返回null。</returns>
public string? GetClientIdByDevice(string deviceId)
{
lock (_syncRoot)
@@ -25,6 +36,14 @@
}
}
+ /// <summary>
+ /// 异步向指定设备发送消息。
+ /// </summary>
+ /// <remarks>如果指定设备未注册或无法找到,则返回 <see langword="false"/>。</remarks>
+ /// <param name="deviceId">目标设备的唯一标识符。不能为null或空。</param>
+ /// <param name="message">要发送给设备的消息。不能为null。</param>
+ /// <returns>表示异步操作的任务。如果消息成功发送,任务结果为 <see langword="true"/>;
+ /// 否则为 <see langword="false"/>。</returns>
public Task<bool> SendToDeviceAsync(string deviceId, string message)
{
var clientId = GetClientIdByDevice(deviceId);
@@ -32,6 +51,16 @@
return SendToClientAsync(clientId, message);
}
+ /// <summary>
+ /// 通过TCP连接异步向指定客户端发送带帧的文本消息。
+ /// </summary>
+ /// <remarks>如果客户端未连接或不存在,此方法将返回 <see langword="false"/> 且不发送消息。
+ /// 消息将优先使用客户端首选的文本编码进行编码;否则使用默认编码。
+ /// 此方法对于向不同客户端的并发调用是线程安全的。</remarks>
+ /// <param name="clientId">要发送消息到的客户端的唯一标识符。必须对应已连接的客户端。</param>
+ /// <param name="message">要发送给客户端的文本消息。不能为null。</param>
+ /// <returns>表示异步操作的任务。如果消息成功发送,任务结果为 <see langword="true"/>;
+ /// 否则,如果客户端未连接或不存在,结果为 <see langword="false"/>。</returns>
public async Task<bool> SendToClientAsync(string clientId, string message)
{
TcpClient? client;
@@ -55,7 +84,8 @@
try
{
var ns = client.GetStream();
- var data = enc.GetBytes((message ?? string.Empty) + "\n");
+ var framedMessage = BuildFramedMessage(message);
+ var data = enc.GetBytes(framedMessage);
await ns.WriteAsync(data, 0, data.Length);
}
finally
@@ -65,6 +95,13 @@
return true;
}
+ /// <summary>
+ /// 异步向所有已连接的客户端发送指定的消息。
+ /// </summary>
+ /// <remarks>如果向某个客户端发送消息时发生错误,异常将被抑制并继续向其他客户端广播。
+ /// 当所有发送操作完成后,此方法结束。</remarks>
+ /// <param name="message">要广播给所有客户端的消息。不能为null。</param>
+ /// <returns>表示异步广播操作的任务。</returns>
public async Task BroadcastAsync(string message)
{
List<TcpClient> clients;
@@ -75,11 +112,19 @@
await Task.WhenAll(clients.Select(c => Task.Run(async () =>
{
- try { await SendAsync(c, message); } catch { }
+ try { await SendMessageAsync(c, message); } catch { }
})));
}
- public static async Task SendAsync(TcpClient client, string message)
+ /// <summary>
+ /// 通过网络流异步向指定的TCP客户端发送带帧的文本消息。
+ /// </summary>
+ /// <remarks>如果客户端为null或未连接,此方法将立即返回而不发送消息。
+ /// 消息将使用配置的文本编码进行编码并添加帧头后通过网络流发送。</remarks>
+ /// <param name="client">要发送消息到的TCP客户端。必须处于连接状态;否则方法不执行任何操作。</param>
+ /// <param name="message">要发送给客户端的文本消息。消息在传输前将被编码并添加帧头。</param>
+ /// <returns>表示异步发送操作的任务。</returns>
+ private async Task SendMessageAsync(TcpClient client, string message)
{
if (client == null || !client.Connected)
{
@@ -87,7 +132,8 @@
}
NetworkStream stream = client.GetStream();
- var data = Encoding.UTF8.GetBytes((message ?? string.Empty) + "\n");
+ var framedMessage = BuildFramedMessage(message);
+ var data = _textEncoding.GetBytes(framedMessage);
await stream.WriteAsync(data, 0, data.Length);
}
}
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Dispose.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Dispose.cs
index d8f5ec9..539df48 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Dispose.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Dispose.cs
@@ -5,6 +5,11 @@
{
public partial class TcpSocketServer
{
+ /// <summary>
+ /// 释放服务器使用的所有资源并停止监听传入连接。
+ /// </summary>
+ /// <remarks>当不再需要服务器时调用此方法,以确保所有相关资源(如网络监听器和同步原语)被正确释放。
+ /// 调用 <see cref="Dispose"/> 后,服务器无法重新启动或再次使用。</remarks>
public void Dispose()
{
_cts?.Cancel();
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
index 9f186e4..a0b8a91 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
@@ -1,16 +1,23 @@
-using HslCommunication.Core.IMessage;
-using System;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using WIDESEAWCS_QuartzJob;
+using System.IO;
namespace WIDESEAWCS_Tasks.SocketServer
{
public partial class TcpSocketServer
{
+ /// <summary>
+ /// 异步处理与已连接的TCP客户端的通信,处理机器人起重机会话中的传入消息和客户端状态更新。
+ /// </summary>
+ /// <remarks>此方法管理客户端连接的生命周期,包括读取消息、更新客户端状态和调用相关事件。
+ /// 当处理结束时,客户端和相关的网络资源将被释放。如果启用心跳或空闲超时选项,
+ /// 将应用额外的取消逻辑。事件调用期间的异常将被捕获并抑制,以确保会话处理的鲁棒性。</remarks>
+ /// <param name="client">表示要处理的远程连接的TCP客户端。方法完成后将释放此对象。</param>
+ /// <param name="clientId">已连接客户端的唯一标识符。用于在整个会话中跟踪和更新客户端状态。</param>
+ /// <param name="cancellationToken">可用于取消客户端处理操作的取消令牌。如果请求取消,方法将立即终止处理。</param>
+ /// <param name="robotCrane">表示与客户端关联的机器人起重机的当前状态对象。用于为消息处理和事件调用提供上下文。</param>
+ /// <returns>表示处理客户端连接的异步操作的任务。当客户端断开连接或请求取消时任务完成。</returns>
public async Task HandleClientAsync(TcpClient client, string clientId, CancellationToken cancellationToken, RobotSocketState robotCrane)
{
using (client)
@@ -32,7 +39,8 @@
try
{
var ct = localCts?.Token ?? cancellationToken;
- message = await reader.ReadLineAsync().WaitAsync(ct);
+ message = await ReceiveFullMessageAsync(networkStream, _textEncoding, ct);
+ //message = await reader.ReadLineAsync().WaitAsync(ct);
}
catch (OperationCanceledException)
{
@@ -55,7 +63,13 @@
if (MessageReceived != null)
{
- try { _ = MessageReceived.Invoke(message, false, client, robotCrane); } catch { }
+ try
+ {
+ // 判断是否为 JSON 格式
+ bool isJsonFormat = TryParseJsonSilent(message);
+ _ = MessageReceived.Invoke(message, isJsonFormat, client, robotCrane);
+ }
+ catch { }
}
}
}
@@ -68,6 +82,18 @@
}
}
+ /// <summary>
+ /// 尝试处理来自客户端的设备注册请求。返回一个值指示该消息是否被作为注册请求处理。
+ /// </summary>
+ /// <remarks>如果消息是有效的注册请求且包含非空的设备标识符,
+ /// 则将设备绑定到客户端并发送确认信息。此方法不会因无效消息而抛出异常;
+ /// 它仅返回 false。</remarks>
+ /// <param name="messageLower">客户端消息的小写版本,用于判断消息是否为注册请求。</param>
+ /// <param name="message">包含注册命令和设备标识符的原始客户端消息。</param>
+ /// <param name="clientId">发送注册请求的客户端的唯一标识符。</param>
+ /// <param name="client">与客户端通信的TCP客户端连接。</param>
+ /// <param name="cancellationToken">可用于取消注册操作的取消令牌。</param>
+ /// <returns>如果消息被识别并作为注册请求处理,则返回 true;否则返回 false。</returns>
private bool TryHandleRegister(string messageLower, string message, string clientId, NetworkStream networkStream, CancellationToken cancellationToken)
{
if (!messageLower.StartsWith("register,"))
@@ -89,6 +115,11 @@
return true;
}
+ /// <summary>
+ /// 更新客户端状态
+ /// </summary>
+ /// <param name="clientId"></param>
+ /// <param name="message"></param>
private void UpdateClientStatus(string clientId, string message)
{
lock (_syncRoot)
@@ -110,6 +141,14 @@
}
}
+ /// <summary>
+ /// 写入消息到客户端
+ /// </summary>
+ /// <param name="clientId"></param>
+ /// <param name="networkStream"></param>
+ /// <param name="message"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
private async Task WriteToClientAsync(string clientId, NetworkStream networkStream, string message, CancellationToken cancellationToken)
{
SemaphoreSlim? sem = null;
@@ -125,7 +164,8 @@
if (sem != null) await sem.WaitAsync(cancellationToken);
try
{
- var data = enc.GetBytes(message + "\n");
+ var framedMessage = BuildFramedMessage(message);
+ var data = enc.GetBytes(framedMessage);
await networkStream.WriteAsync(data, 0, data.Length, cancellationToken);
}
finally
@@ -134,6 +174,23 @@
}
}
+ /// <summary>
+ /// 添加消息帧头尾
+ /// </summary>
+ /// <param name="message"></param>
+ /// <returns></returns>
+ private string BuildFramedMessage(string message)
+ {
+ var header = _options.MessageHeader ?? string.Empty;
+ var footer = _options.MessageFooter ?? string.Empty;
+ return header + (message ?? string.Empty) + footer;
+ }
+
+ /// <summary>
+ /// JSON格式尝试解析(静默失败)
+ /// </summary>
+ /// <param name="message"></param>
+ /// <returns></returns>
private static bool TryParseJsonSilent(string message)
{
if (string.IsNullOrWhiteSpace(message)) return false;
@@ -142,6 +199,11 @@
try { JsonDocument.Parse(message); return true; } catch { return false; }
}
+ /// <summary>
+ /// utf-8 可能性检测
+ /// </summary>
+ /// <param name="data"></param>
+ /// <returns></returns>
private static bool IsLikelyUtf8(byte[] data)
{
int i = 0;
@@ -171,5 +233,58 @@
}
return true;
}
+
+ /// <summary>
+ /// 读取完整消息
+ /// </summary>
+ /// <param name="networkStream">字节流</param>
+ /// <param name="encoding">编码格式</param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ private async Task<string?> ReceiveFullMessageAsync(NetworkStream networkStream, Encoding encoding, CancellationToken cancellationToken)
+ {
+ var header = _options.MessageHeader ?? string.Empty;
+ var footer = _options.MessageFooter ?? string.Empty;
+
+ var buffer = new byte[1024];
+ var builder = new StringBuilder();
+
+ while (true)
+ {
+ int bytesRead = await networkStream.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken);
+ if (bytesRead <= 0)
+ {
+ if (builder.Length == 0) return null;
+ return string.IsNullOrEmpty(header) && string.IsNullOrEmpty(footer) ? builder.ToString() : null;
+ }
+
+ builder.Append(encoding.GetString(buffer, 0, bytesRead));
+
+ if (string.IsNullOrEmpty(header) && string.IsNullOrEmpty(footer))
+ {
+ if (!networkStream.DataAvailable)
+ {
+ break;
+ }
+ continue;
+ }
+
+ var data = builder.ToString();
+ var headerIndex = string.IsNullOrEmpty(header) ? 0 : data.IndexOf(header, StringComparison.Ordinal);
+ if (headerIndex < 0)
+ {
+ continue;
+ }
+
+ var startIndex = headerIndex + header.Length;
+ var footerIndex = string.IsNullOrEmpty(footer) ? data.Length : data.IndexOf(footer, startIndex, StringComparison.Ordinal);
+ if (footerIndex >= 0)
+ {
+ return data.Substring(startIndex, footerIndex - startIndex);
+ }
+ }
+
+ return builder.ToString();
+ }
}
}
\ No newline at end of file
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs
index 2c35f71..d3c401b 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs
@@ -10,6 +10,13 @@
{
public partial class TcpSocketServer
{
+ /// <summary>
+ /// 异步启动TCP服务器,使其开始接受传入的客户端连接。
+ /// </summary>
+ /// <remarks>如果服务器已在运行或通过配置禁用,此方法将立即返回而不启动服务器。
+ /// 后续的客户端监控和接受操作在后台任务中运行。此方法不会阻塞调用线程。</remarks>
+ /// <param name="cancellationToken">可用于请求取消服务器启动及后续后台操作的取消令牌。</param>
+ /// <returns>表示异步启动操作的任务。当服务器开始监听连接时任务完成。</returns>
public Task StartAsync(CancellationToken cancellationToken)
{
if (IsRunning || !_options.Enabled)
@@ -34,6 +41,13 @@
return Task.CompletedTask;
}
+ //// <summary>
+ /// 异步停止服务器并等待所有活动客户端连接完成。
+ /// </summary>
+ /// <remarks>如果服务器未运行,此方法将立即返回而不执行任何操作。
+ /// 此方法确保所有客户端任务完成后才将服务器标记为已停止。</remarks>
+ /// <param name="cancellationToken">可用于在完成前取消停止操作的取消令牌。</param>
+ /// <returns>表示异步停止操作的任务。</returns>
public async Task StopAsync(CancellationToken cancellationToken)
{
if (!IsRunning)
@@ -58,6 +72,13 @@
IsRunning = false;
}
+ /// <summary>
+ /// 持续接受传入的TCP客户端连接,直到请求取消。
+ /// </summary>
+ /// <remarks>此方法旨在后台运行以处理新的客户端连接。
+ /// 如果监听器被释放或通过提供的令牌请求取消,循环将退出。</remarks>
+ /// <param name="cancellationToken">可用于请求取消接受循环的令牌。当请求取消时,循环将立即终止。</param>
+ /// <returns>表示异步接受循环操作的任务。</returns>
private async Task AcceptLoopAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
@@ -97,6 +118,12 @@
}
}
+ /// <summary>
+ /// 从内部集合中移除指定标识符的客户端,并释放相关资源。
+ /// </summary>
+ /// <remarks>此方法关闭客户端连接,释放任何关联的锁,并移除对客户端的所有引用,
+ /// 包括设备绑定和编码信息。通过对内部同步对象加锁确保线程安全。</remarks>
+ /// <param name="clientId">要移除的客户端的唯一标识符。不能为null或空。</param>
private void RemoveClient(string clientId)
{
lock (_syncRoot)
@@ -124,6 +151,13 @@
}
}
+ /// <summary>
+ /// 异步监控已连接的客户端,并断开超过配置超时时间闲置的客户端连接。
+ /// </summary>
+ /// <remarks>此方法持续检查闲置客户端,如果其不活动时间超过指定的空闲超时,则断开连接。
+ /// 监控循环将持续运行,直到通过提供的令牌请求取消。</remarks>
+ /// <param name="cancellationToken">可用于请求终止监控循环的取消令牌。</param>
+ /// <returns>表示异步监控操作的任务。</returns>
private async Task MonitorClientsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
@@ -156,6 +190,13 @@
}
}
+ /// <summary>
+ /// 基于远程终端点获取指定TCP客户端的唯一标识符字符串。
+ /// </summary>
+ /// <remarks>返回的标识符适用于在日志记录或跟踪场景中区分客户端。
+ /// 如果客户端的远程终端点不可用,将生成GUID以确保唯一性。</remarks>
+ /// <param name="client">要获取标识符的TCP客户端。不能为null。</param>
+ /// <returns>表示客户端远程终端点的字符串(如果可用);否则为生成的新GUID字符串。</returns>
public static string GetClientId(TcpClient client)
{
return client.Client.RemoteEndPoint?.ToString() ?? Guid.NewGuid().ToString();
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs
index 16371be..4d8789b 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs
@@ -16,20 +16,81 @@
public partial class TcpSocketServer : IDisposable
{
private readonly SocketServerOptions _options;
+
+ /// <summary>
+ /// 提供一个可用于同步对包含实例的访问的对象。
+ /// </summary>
+ /// <remarks>在对实例实现线程安全操作时,可将此对象用作锁定目标。此模式通常用于避免死锁并确保一致的同步。</remarks>
public readonly object _syncRoot = new();
+
private TcpListener? _listener;
+
+ /// <summary>
+ /// 表示用于发出进行中操作的取消请求的取消令牌源。
+ /// </summary>
+ /// <remarks>如果当前没有活动的取消机制,此字段可能为null。使用此令牌源取消支持取消的任务或操作。</remarks>
public CancellationTokenSource? _cts;
+
+ /// <summary>
+ /// 提供表示活动客户端操作的任务列表。
+ /// </summary>
+ /// <remarks>此字段用于内部跟踪异步客户端活动。它是只读的,不应在包含类外部直接修改。</remarks>
public readonly List<Task> _clientTasks = new();
+
+ /// <summary>
+ /// 提供从客户端标识符到其关联的TCP客户端连接的映射。
+ /// </summary>
+ /// <remarks>此字典允许通过唯一字符串标识符访问活动的TCP客户端。在多线程场景中,对集合的修改应小心进行以避免并发问题。</remarks>
public readonly Dictionary<string, TcpClient> _clients = new();
+
+ /// <summary>
+ /// 提供从设备标识符到其对应绑定值的映射。
+ /// </summary>
+ /// <remarks>此字段是只读的,用于包含类内部使用。应通过指定的方法或属性对字典进行修改以确保一致性。</remarks>
public readonly Dictionary<string, string> _deviceBindings = new();
+
+ /// <summary>
+ /// 提供从客户端标识符到其关联锁的映射,用于同步对客户端特定资源的访问。
+ /// </summary>
+ /// <remarks>字典中的每个条目将一个唯一的客户端ID与一个<see cref="SemaphoreSlim"/>实例关联,实现每个客户端的线程安全操作。此集合用于内部协调并发访问,不应直接修改。</remarks>
public readonly Dictionary<string, SemaphoreSlim> _clientLocks = new();
+
+ /// <summary>
+ /// 提供从客户端标识符到其关联文本编码的映射。
+ /// </summary>
+ /// <remarks>此字典用于内部跟踪已连接客户端的编码偏好。键表示客户端标识符,值指定用于文本操作的对应<see cref="System.Text.Encoding"/>。</remarks>
public readonly Dictionary<string, Encoding> _clientEncodings = new();
+
+ /// <summary>
+ /// 存储每个客户端最后活动的时间戳,以客户端标识符为键。
+ /// </summary>
+ /// <remarks>此字段用于内部跟踪客户端活动。字典将客户端标识符映射到对应的最后活动时间(UTC)。直接修改此集合可能影响客户端会话管理逻辑。</remarks>
public readonly Dictionary<string, DateTime> _clientLastActive = new();
+
+ /// <summary>
+ /// 指定包含类型中字符数据使用的文本编码。
+ /// </summary>
+ /// <remarks>使用此字段确定处理字符数据时如何编码或解码文本。编码影响字节如何被解释为字符,反之亦然。常见的编码包括UTF8、ASCII和Unicode。</remarks>
public readonly Encoding _textEncoding;
+
+ /// <summary>
+ /// 表示自动检测到的GB2312编码(如果可用)。
+ /// </summary>
+ /// <remarks>通常从输入数据确定编码时设置此字段。如果检测失败或未执行检测,值可能为null。</remarks>
public readonly Encoding? _autoDetectedGb2312;
+
private readonly string _logFile;
+
private Task? _monitorTask;
+ /// <summary>
+ /// 使用指定的服务器选项初始化 TcpSocketServer 类的新实例。
+ /// </summary>
+ /// <remarks>如果启用了 AutoDetectEncoding 选项,服务器将默认使用 UTF-8 编码,
+ /// 并尝试支持 GBK 编码进行自动检测。如果编码检测失败或提供了无效的编码名称,
+ /// 将回退使用 UTF-8 编码。日志文件路径由 LogFilePath 选项决定,
+ /// 如果未指定,则默认为应用程序基目录下的 'socketserver.log' 文件。</remarks>
+ /// <param name="options">套接字服务器的配置选项。不能为 null。提供编码设置、日志文件路径和自动检测行为等配置。</param>
public TcpSocketServer(IOptions<SocketServerOptions> options)
{
_options = options.Value;
@@ -52,6 +113,7 @@
public bool IsRunning { get; private set; }
public event Func<string, bool, TcpClient, RobotSocketState, Task<string?>>? MessageReceived;
+
public event Func<string, Task<string?>>? RobotReceived;
private void Log(string message)
diff --git "a/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\213\230\346\235\237\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256/\346\217\222\346\213\224\351\222\211\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256.xlsx" "b/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\213\230\346\235\237\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256/\346\217\222\346\213\224\351\222\211\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256.xlsx"
new file mode 100644
index 0000000..9f1bfcc
--- /dev/null
+++ "b/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\213\230\346\235\237\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256/\346\217\222\346\213\224\351\222\211\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256.xlsx"
Binary files differ
--
Gitblit v1.9.3