The TCP server is unable to respond to connection and data reception events from the Python client, but it can respond to client disconnection events.
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using WatsonTcp;
namespace TcpServer
{
internal class Program
{
// 和Python端完全一致的配置
private const string SERVER_IP = "localhost";
private const int SERVER_PORT = 5555;
private const int HEAD_SIZE = 8; // 固定包头8字节
private static WatsonTcpServer _tcpServer;
static void Main(string[] args)
{
// 1. 创建WatsonTcp服务端实例
_tcpServer = new WatsonTcpServer(SERVER_IP, SERVER_PORT);
// 2. 绑定核心事件
_tcpServer.Events.ClientConnected += TcpServer_ClientConnected; // 客户端连接事件
_tcpServer.Events.ClientDisconnected += TcpServer_ClientDisconnected;// 客户端断开事件
_tcpServer.Events.MessageReceived += TcpServer_MessageReceived; // 接收消息核心事件
// 3. 启动服务端
_tcpServer.Start();
Console.WriteLine($"服务端已启动:{SERVER_IP}:{SERVER_PORT}");
Console.WriteLine("等待Python客户端连接...\r\n");
// 防止控制台退出
Console.ReadLine();
}
/// <summary>
/// 客户端连接成功回调
/// </summary>
private static void TcpServer_ClientConnected(object sender, ConnectionEventArgs args)
{
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 客户端已连接:{args.Client.IpPort}");
}
/// <summary>
/// 客户端断开连接回调
/// </summary>
private static void TcpServer_ClientDisconnected(object sender, DisconnectionEventArgs args)
{
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 客户端已断开:{args.Client.IpPort}");
}
/// <summary>
/// 核心:接收并解析Python发送的TCP消息
/// </summary>
private static void TcpServer_MessageReceived(object sender, MessageReceivedEventArgs args)
{
try
{
// 接收的完整字节流
byte[] receiveBytes = args.Data;
// 校验:消息长度至少要包含完整包头
if (receiveBytes.Length < HEAD_SIZE)
{
Console.WriteLine("接收的数据不完整,缺少包头");
return;
}
#region 第一步:解析8字节包头
// 1-1 前4字节:魔法标识 UFIX 校验
byte[] magicCode = receiveBytes.Take(4).ToArray();
string magicStr = Encoding.ASCII.GetString(magicCode);
if (magicStr != "UFIX")
{
Console.WriteLine($"非法数据包,魔法标识校验失败,收到:{magicStr}");
return;
}
// 1-2 后4字节:解析【大端序】的压缩体长度 (Python struct.I 对应 uint32 大端序)
byte[] lenBytes = receiveBytes.Skip(4).Take(4).ToArray();
// ★★★ 关键:Python的struct.pack是【大端序】,C#默认小端序,必须反转字节数组 ★★★
if (BitConverter.IsLittleEndian) Array.Reverse(lenBytes);
uint compressBodyLen = BitConverter.ToUInt32(lenBytes, 0);
#endregion
#region 第二步:解析zlib压缩包体
// 提取包头后的压缩体字节数组
byte[] compressBody = receiveBytes.Skip(HEAD_SIZE).Take((int)compressBodyLen).ToArray();
if (compressBody.Length != compressBodyLen)
{
Console.WriteLine($"压缩体长度不匹配,预期:{compressBodyLen},实际:{compressBody.Length}");
return;
}
#endregion
#region 第三步:zlib解压 + UTF8解码(和Python端完全逆向操作)
// Python: content.encode("utf-8") → zlib.compress → 发送
// C#: 接收压缩体 → zlib.decompress → UTF8.GetString → 原始字符串
byte[] decompressBody = Decompress(compressBody);
string content = Encoding.UTF8.GetString(decompressBody);
#endregion
// 解析成功,打印结果
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 解析成功 → 原始内容:{content}");
}
catch (Exception ex)
{
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 解析消息异常:{ex.Message}");
}
}
private static byte[] Decompress(byte[] data)
{
using (var compressedStream = new MemoryStream(data))
using (var zipStream = new ZLibStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
}
public static byte[] Compress(byte[] data)
{
using (var ms = new MemoryStream())
{
using (var zlibStream = new ZLibStream(ms, CompressionLevel.Optimal))
{
zlibStream.Write(data, 0, data.Length);
}
return ms.ToArray();
}
}
}
}
import socket
import time
import struct
import zlib
SERVERIP = "localhost"
# 必填: 服务端端口
SERVERPORT = 5555
HEAD_SIZE = 8
RECEIVE_BUFFER_SIZE = 2048
test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
test_socket.connect((SERVERIP, SERVERPORT))
test_socket.setblocking(False)
time.sleep(1)
while True:
content = '你好123'
body = content.encode("utf-8")
compressed_body = zlib.compress(body)
compressed_body_len = len(compressed_body)
format_str = f'4sI{compressed_body_len}s'
data = struct.pack(format_str, b'UFIX',
compressed_body_len, compressed_body)
test_socket.sendall(data)
time.sleep(1)
The TCP server is unable to respond to connection and data reception events from the Python client, but it can respond to client disconnection events.