激光打标机TCP Socket通信协议:KZ指令集实战
一、引言
定位到打标区域后,上位机需要控制激光打标机执行打标。本项目通过TCP Socket 与打标机软件通信,使用一套自定义的KZ指令集 。本文从第一性原理出发,讲解TCP通信的本质,并结合项目中的Laser.cs代码,深入剖析Socket连接、指令收发、协议握手、打标流程等关键技术。
二、第一性原理:TCP通信的本质
2.1 什么是TCP
TCP(Transmission Control Protocol)是互联网的基础传输协议,提供可靠的、面向连接的字节流传输。与UDP不同,TCP保证数据按序到达、不丢失、不重复。
2.2 客户端/服务器模型
TCP通信采用客户端/服务器(C/S)模型:
- 服务器(Server):监听端口,等待连接。
- 客户端(Client):主动连接服务器。
本项目上位机是客户端 ,打标机软件是服务器。上位机主动连接打标机的IP和端口。
2.3 长连接与短连接
TCP连接有两种模式:
- 短连接:每次通信都建立连接,用后即断。
- 长连接:建立一次连接,多次通信,用后关闭。
本项目使用长连接,因为打标流程包含多个步骤(连接、加载模板、设置内容、执行、关闭),需要保持连接状态。
三、项目中的TCP通信
3.1 连接参数
在Laser.cs中,定义了服务器地址和端口:
csharp
private const string serverIP = "192.168.30.31"; // 打标机IP
private const int port = 6060; // 打标机端口
3.2 创建TCP连接
CreateTcp方法建立TCP连接:
csharp
private bool CreateTcp()
{
try
{
client = new TcpClient(serverIP, port); // 长连接
Thread.Sleep(100);
stream = client.GetStream(); // 获取网络流
string response = ReceiveResponse();
response = response.Replace("\r\n", ""); // 去掉换行
if (response == "OK")
{
return true;
}
else
{
Console.WriteLine("创建Tcp失败");
return false;
}
}
catch (Exception ex)
{
Console.WriteLine("创建Tcp失败:" + ex.Message);
return false;
}
}
关键点:
new TcpClient(serverIP, port):创建TCP客户端并连接服务器。client.GetStream():获取网络流,用于读写数据。Thread.Sleep(100):等待服务器响应。- 握手验证:连接后接收服务器返回的"OK",验证连接成功。
3.3 发送指令
SendCommand方法发送指令:
csharp
private void SendCommand(string command)
{
if (stream != null && stream.CanWrite)
{
byte[] data = Encoding.ASCII.GetBytes(command);
stream.Write(data, 0, data.Length);
}
}
指令以ASCII编码发送,以\r\n结尾(如"KZOpenRequest\r\n")。
3.4 接收响应
ReceiveResponse方法接收响应:
csharp
private string ReceiveResponse()
{
if (stream != null && stream.CanRead)
{
try
{
byte[] data = new byte[1024];
int bytes = stream.Read(data, 0, data.Length);
Console.WriteLine("Received bytes: " + bytes);
if (bytes > 0)
{
Console.WriteLine("Raw data: " + BitConverter.ToString(data, 0, bytes));
string response = Encoding.UTF8.GetString(data, 0, bytes);
return response;
}
else
{
MessageBox.Show("No data received from server.");
return null;
}
}
catch (Exception ex)
{
MessageBox.Show("Error receiving response: " + ex.Message);
return null;
}
}
return null;
}
四、KZ指令集详解
4.1 指令集概览
项目使用的KZ指令集包括:
| 指令 | 方向 | 说明 |
|---|---|---|
KZOpenRequest |
上位机→打标机 | 请求打开 |
KZOpenOk |
打标机→上位机 | 打开成功 |
KZSetFile: 路径 |
上位机→打标机 | 加载模板文件 |
KZSetFile |
打标机→上位机 | 模板加载成功 |
KZSetContent: TEXT1,内容 |
上位机→打标机 | 设置打标内容 |
KZSetContentOK |
打标机→上位机 | 内容设置成功 |
KZRequest |
上位机→打标机 | 请求执行打标 |
KZFinished |
打标机→上位机 | 打标完成 |
KZCloseRequest |
上位机→打标机 | 请求关闭 |
KZCloseOK |
打标机→上位机 | 关闭成功 |
4.2 指令格式
指令采用文本协议,格式为:
指令名[: 参数]\r\n
- 指令名:如
KZOpenRequest。 - 参数:可选,用冒号分隔,如
KZSetFile: D:\template.txt。 - 结尾:
\r\n(回车换行)。
4.3 响应匹配
上位机发送指令后,接收响应并匹配:
csharp
private bool ConnectTcp()
{
try
{
SendCommand("KZOpenRequest\r\n"); // 发送打开请求
Thread.Sleep(100);
string response = ReceiveResponse();
response = response.Replace("\r\n", ""); // 去掉换行
if (response == "KZOpenOk") // 匹配响应
{
return true;
}
else
{
Console.WriteLine("连接失败");
return false;
}
}
catch (Exception ex)
{
Console.WriteLine("连接失败:" + ex.Message);
return false;
}
}
五、完整打标流程
5.1 Run方法
Run方法编排了完整的打标流程:
csharp
public void Run()
{
bool ret;
ret = CreateTcp(); // 1. 创建TCP连接
if (!ret) { return; }
ret = ConnectTcp(); // 2. 打开连接
if (!ret) { stream.Close(); client.Close(); return; }
ret = LoadTemplate(); // 3. 加载模板
if (!ret) { stream.Close(); client.Close(); return; }
ret = LoadContent(); // 4. 设置内容
if (!ret) { stream.Close(); client.Close(); return; }
ret = Engrave(); // 5. 执行打标
if (!ret) { stream.Close(); client.Close(); return; }
ret = CloseTcp(); // 6. 关闭连接
if (!ret) { stream.Close(); client.Close(); return; }
stream.Close();
client.Close();
}
5.2 流程状态机
这个流程是一个顺序状态机:
创建连接 → 打开 → 加载模板 → 设置内容 → 执行打标 → 关闭
每一步都检查返回值,失败则中断并关闭连接。这种"顺序执行、失败即停"的模式,保证了打标流程的可靠性。
5.3 加载模板
LoadTemplate方法加载打标模板:
csharp
private bool LoadTemplate()
{
try
{
SendCommand("KZSetFile: " + CConfig.TemplatePath + "\r\n"); // 发送模板路径
Thread.Sleep(100);
string response = ReceiveResponse();
if (response == "KZSetFile") // 匹配响应
{
return true;
}
else
{
Console.WriteLine("加载模板失败");
return false;
}
}
catch (Exception ex)
{
Console.WriteLine("加载模板失败:" + ex.Message);
return false;
}
}
模板路径从配置中读取(CConfig.TemplatePath),通过KZSetFile指令发送给打标机。
5.4 设置内容
LoadContent方法设置打标内容:
csharp
private bool LoadContent()
{
try
{
SendCommand("KZSetContent: TEXT1,公司名称\r\n"); // 设置内容
Thread.Sleep(100);
string response = ReceiveResponse();
if (response == "KZSetContentOK")
{
return true;
}
else
{
Console.WriteLine("设置内容失败");
return false;
}
}
catch (Exception ex)
{
Console.WriteLine("设置内容失败:" + ex.Message);
return false;
}
}
KZSetContent: TEXT1,公司名称表示在TEXT1文本框中设置内容为"公司名称"。
5.5 执行打标
Engrave方法执行打标:
csharp
private bool Engrave()
{
try
{
SendCommand("KZRequest\r\n"); // 请求打标
Thread.Sleep(1000); // 等待打标完成
string response = ReceiveResponse();
if (response == "KZFinished") // 打标完成
{
return true;
}
else
{
Console.WriteLine("打标失败");
return false;
}
}
catch (Exception ex)
{
Console.WriteLine("打标失败:" + ex.Message);
return false;
}
}
打标是耗时操作,Thread.Sleep(1000)等待1秒后接收"KZFinished"响应。
六、打标控制界面
6.1 LaserLettering窗体
项目还提供了一个独立的打标控制界面LaserLettering.cs,允许用户手动控制打标流程:
csharp
private void SetConnect_Click(object sender, EventArgs e)
{
client = new TcpClient(serverIP, port); // 连接
Thread.Sleep(1000);
stream = client.GetStream();
string response = ReceiveResponse();
response = response.Replace("\r\n", "");
if (response == "OK") { }
else { MessageBox.Show("Failed to connect to server."); }
}
这个界面提供了连接、打开、设置内容、执行、关闭等按钮,方便调试和手动操作。
6.2 手动控制按钮
LaserLettering界面包含多个控制按钮:
- SetConnect:连接服务器。
- ConformConnect:确认连接(发送KZOpenRequest)。
- SetContent:设置内容。
- ExecuteEngrave:执行打标。
- CloseEquipment:关闭设备。
- Run:一键执行完整流程。
七、TCP通信的工程要点
7.1 可靠性设计
- 握手验证:连接后验证"OK"响应,确保连接成功。
- 响应匹配:每条指令都匹配预期响应,失败即中断。
- 异常处理:用try/catch捕获通信异常。
7.2 时序控制
Thread.Sleep:指令间用Sleep等待响应,避免发送过快。- 超时:打标等耗时操作需要足够长的等待时间。
7.3 协议设计建议
- 指令规范化:指令名、参数格式统一。
- 响应明确:每个指令有明确的成功/失败响应。
- 版本管理:协议变更时做好版本兼容。
八、总结
本文从第一性原理出发,讲解了激光打标机TCP Socket通信协议:
- TCP通信本质:可靠的字节流传输,C/S模型。
- 长连接:一次连接多次通信。
- KZ指令集:文本协议,指令+参数+换行。
- 打标流程:创建→打开→加载模板→设置内容→执行→关闭。
- 状态机:顺序执行、失败即停。
TCP通信是上位机控制外部设备的重要手段。下一篇文章将深入讲解INI配置文件读写技术。