cs
private async Task ProcessRequestAsync(HttpListenerContext context)
{
try
{
var request = context.Request;
var response = context.Response;
// 步骤1:只处理POST请求
if (request.HttpMethod != "POST")
{
response.StatusCode = 405;
await WriteSimpleResponse(response, "只支持POST请求");
return;
}
// 步骤2:读取并解析请求数据
string jsonBody = await ReadRequestBody(request);
dynamic data = ParseJson(jsonBody);
if (data == null)
{
response.StatusCode = 400;
await WriteSimpleResponse(response, "无效的JSON数据");
return;
}
// 步骤3:验证必要字段
if (string.IsNullOrEmpty(data.method?.ToString()) ||
string.IsNullOrEmpty(data.reqCode?.ToString()))
{
await WriteErrorResponse(response, data?.reqCode, "缺少method或reqCode字段");
return;
}
// 步骤4:查找对应工位
int stationIndex = FindStationIndex(data.reqCode.ToString());
if (stationIndex == -1)
{
await WriteErrorResponse(response, data.reqCode, "未找到对应的工位配置");
return;
}
// 步骤5:根据方法类型处理
string method = data.method.ToString();
bool success = await ExecuteStationAction(method, stationIndex);
if (success)
{
await WriteSuccessResponse(response, data.reqCode);
}
else
{
await WriteErrorResponse(response, data.reqCode, "执行操作失败");
}
}
catch (Exception ex)
{
Console.WriteLine($"处理请求错误: {ex.Message}");
}
finally
{
context.Response.Close();
}
}
// 辅助方法
private async Task<string> ReadRequestBody(HttpListenerRequest request)
{
using var reader = new StreamReader(request.InputStream, request.ContentEncoding);
return await reader.ReadToEndAsync();
}
private dynamic ParseJson(string json)
{
try
{
return JsonConvert.DeserializeObject(json);
}
catch
{
return null;
}
}
private int FindStationIndex(string requestCode)
{
var configs = FrmConfig.GetInstance().taskConfigs;
for (int i = 0; i < configs.Count; i++)
{
if (configs[i] == requestCode) return i;
}
return -1;
}
private async Task<bool> ExecuteStationAction(string method, int stationIndex)
{
try
{
switch (method)
{
case "Wait":
int address = PlcCommunication.GetInstance().plcAddressOffset(stationIndex);
PlcCommunication.GetInstance().myPLC.WriteSingleRegister((ushort)address, 3);
Log($"发送继续信号到工位{stationIndex}");
return true;
case "Arrive":
FrmShow.stationInfos[stationIndex].Status = 0;
Log($"工位{stationIndex}任务完成,状态重置");
return true;
default:
Log($"未知方法: {method}");
return false;
}
}
catch (Exception ex)
{
Log($"执行失败: {ex.Message}");
return false;
}
}
private void Log(string message)
{
Console.WriteLine($"[{DateTime.Now}] {message}");
FrmShow.GetInstance()?.ucLogShow?.LogInfo(message);
}
private async Task WriteSimpleResponse(HttpListenerResponse response, string message)
{
await WriteJsonResponse(response, new { code = "error", message });
}
private async Task WriteSuccessResponse(HttpListenerResponse response, object reqCode)
{
await WriteJsonResponse(response, new { reqCode, code = "0", message = "成功" });
}
private async Task WriteErrorResponse(HttpListenerResponse response, object reqCode, string message)
{
await WriteJsonResponse(response, new { reqCode, code = "99", message });
}
ProcessRequestAsync (主入口)
↓
ReadRequestBody → 读取HTTP请求体
↓
ParseJson → 解析JSON为对象
↓
FindStationIndex → 查找工位索引
↓
ExecuteStationAction → 执行具体操作
├── Wait操作 → 写入PLC
└── Arrive操作 → 更新状态
↓
WriteSuccessResponse/WriteErrorResponse → 返回响应
↓
Log → 记录日志
方法作用详细解释
让我逐一解释每个方法的作用:
1. 主处理方法 - ProcessRequestAsync
cs
private async Task ProcessRequestAsync(HttpListenerContext context)
作用:这是HTTP请求的主处理器,负责协调整个请求处理流程。
执行流程:
-
步骤1:检查是否是POST请求,不是则返回405错误
-
步骤2:读取并解析JSON请求体
-
步骤3:验证必要字段(method和reqCode)
-
步骤4:根据reqCode查找对应的工位
-
步骤5:根据method类型执行具体操作
-
步骤6:返回成功或失败响应
2. 读取请求体 - ReadRequestBody
cs
private async Task<string> ReadRequestBody(HttpListenerRequest request)
{
using var reader = new StreamReader(request.InputStream, request.ContentEncoding);
return await reader.ReadToEndAsync();
}
作用:从HTTP请求中读取完整的请求体内容。
工作原理解释:
-
request.InputStream:获取请求的原始数据流(字节流) -
StreamReader:将字节流转换为可读的文本 -
request.ContentEncoding:使用请求指定的编码方式(如UTF-8) -
ReadToEndAsync():异步读取所有内容直到末尾 -
using:确保使用后自动释放资源
示例:
javascript
// 输入请求体
{"method":"Wait","reqCode":"STATION_01"}
// 方法返回
"{\"method\":\"Wait\",\"reqCode\":\"STATION_01\"}"
3. 解析JSON - ParseJson
cs
private dynamic ParseJson(string json)
{
try
{
return JsonConvert.DeserializeObject(json);
}
catch
{
return null;
}
}
作用:将JSON字符串解析为动态对象,方便访问属性。
特点:
-
使用
dynamic类型,可以直接访问属性(如data.method) -
异常安全:解析失败返回null,不会抛出异常
-
使用Newtonsoft.Json库(JsonConvert)
示例:
cs
// 输入
string json = "{\"method\":\"Wait\",\"reqCode\":\"STATION_01\"}";
// 输出(dynamic对象)
data.method // "Wait"
data.reqCode // "STATION_01"
4. 查找工位索引 - FindStationIndex
cs
private int FindStationIndex(string requestCode)
{
var configs = FrmConfig.GetInstance().taskConfigs;
for (int i = 0; i < configs.Count; i++)
{
if (configs[i] == requestCode) return i;
}
return -1;
}
作用:根据请求码(reqCode)在配置列表中查找对应的工位索引。
工作原理:
-
从全局配置
FrmConfig获取任务配置列表taskConfigs -
遍历列表,查找与requestCode匹配的项
-
返回匹配项的索引位置
-
找不到返回-1
示例:
cs
// taskConfigs 内容: ["STATION_01", "STATION_02", "STATION_03"]
FindStationIndex("STATION_02") // 返回 1
FindStationIndex("STATION_05") // 返回 -1
5. 执行工位操作 - ExecuteStationAction
cs
private async Task<bool> ExecuteStationAction(string method, int stationIndex)
作用:根据方法类型执行具体的工位操作。
两种操作类型:
Wait操作(任务等待)
cs
case "Wait":
int address = PlcCommunication.GetInstance().plcAddressOffset(stationIndex);
PlcCommunication.GetInstance().myPLC.WriteSingleRegister((ushort)address, 3);
Log($"发送继续信号到工位{stationIndex}");
return true;
-
计算PLC的偏移地址
-
向PLC写入值3(继续任务信号)
-
记录操作日志
Arrive操作(任务完成)
cs
case "Arrive":
FrmShow.stationInfos[stationIndex].Status = 0;
Log($"工位{stationIndex}任务完成,状态重置");
return true;
-
将工位状态重置为0(空闲状态)
-
记录操作日志
6. 日志记录 - Log
cs
private void Log(string message)
{
Console.WriteLine($"[{DateTime.Now}] {message}");
FrmShow.GetInstance()?.ucLogShow?.LogInfo(message);
}
作用:同时向控制台和UI界面记录日志信息。
特点:
-
添加时间戳
-
同时输出到控制台和UI日志控件
-
使用
?.安全调用,防止空引用
7. 响应处理方法
简单响应 - WriteSimpleResponse
cs
private async Task WriteSimpleResponse(HttpListenerResponse response, string message)
{
await WriteJsonResponse(response, new { code = "error", message });
}
作用:返回简单的错误响应(无reqCode)
输出示例:
javascript
{"code":"error","message":"只支持POST请求"}
成功响应 - WriteSuccessResponse
cs
private async Task WriteSuccessResponse(HttpListenerResponse response, object reqCode)
{
await WriteJsonResponse(response, new { reqCode, code = "0", message = "成功" });
}
作用:返回操作成功的响应
输出示例:
javascript
{"reqCode":"STATION_01","code":"0","message":"成功"}
错误响应 - WriteErrorResponse
cs
private async Task WriteErrorResponse(HttpListenerResponse response, object reqCode, string message)
{
await WriteJsonResponse(response, new { reqCode, code = "99", message });
}
作用:返回操作失败的响应
输出示例:
javascript
{"reqCode":"STATION_01","code":"99","message":"未找到对应的工位配置"}
8. JSON响应写入 - WriteJsonResponse
(这是原有代码中的方法,不是新加的)
cs
private async Task WriteJsonResponse(HttpListenerResponse response, object data)
{
string json = System.Text.Json.JsonSerializer.Serialize(data);
byte[] buffer = Encoding.UTF8.GetBytes(json);
response.ContentType = "application/json";
response.ContentLength64 = buffer.Length;
await response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
}
作用:将对象序列化为JSON并写入HTTP响应