C# Socket实现客户端与服务端双向传输自定义对象的方法
C# Socket传输自定义Message对象的实现方案
你之前遇到无法序列化的报错,本质是没有给自定义类配置对应的序列化支持,以下提供两种简单可落地的实现方式:
方案1:JSON序列化(推荐,易调试无额外依赖)
无需修改原有Message类定义,直接用JSON作为中间格式转字节数组,新手不易踩坑,.NET Core 3.0+/.NET 5+自带System.Text.Json库可直接使用,.NET Framework可替换为Newtonsoft.Json实现,逻辑完全一致。
发送端修改
将你原代码中发送部分的逻辑替换为以下内容:
if (message.Content != null) { // 1. 将Message对象序列化为JSON字符串 string jsonMsg = System.Text.Json.JsonSerializer.Serialize(message); // 2. 转成UTF8字节数组(比ASCII支持更全面的字符) byte[] msgBytes = System.Text.Encoding.UTF8.GetBytes(jsonMsg); // 可选优化:先发4字节的消息长度,解决TCP粘包问题 byte[] lenBytes = BitConverter.GetBytes(msgBytes.Length); clientSocket.Send(lenBytes); // 3. 发送实际消息内容 clientSocket.Send(msgBytes); // 接收响应逻辑 // 先读4字节拿到响应长度 byte[] lenBuffer = new byte[4]; clientSocket.Receive(lenBuffer); int respLen = BitConverter.ToInt32(lenBuffer, 0); // 再读对应长度的响应内容 byte[] respBuffer = new byte[respLen]; int received = clientSocket.Receive(respBuffer); // 反序列化为Message对象 string respJson = System.Text.Encoding.UTF8.GetString(respBuffer, 0, received); Message respMsg = System.Text.Json.JsonSerializer.Deserialize<Message>(respJson); Console.WriteLine($"收到响应:类型={respMsg.Type},内容={respMsg.Content}"); }
接收端对应逻辑
// 接收消息的通用逻辑 byte[] lenBuffer = new byte[4]; socket.Receive(lenBuffer); int msgLen = BitConverter.ToInt32(lenBuffer, 0); byte[] msgBuffer = new byte[msgLen]; int receivedCount = socket.Receive(msgBuffer); string json = Encoding.UTF8.GetString(msgBuffer, 0, receivedCount); Message receivedMsg = JsonSerializer.Deserialize<Message>(json);
方案2:二进制序列化(性能更高)
适合对传输性能要求较高的场景,需要先给Message类标记可序列化特性:
[Serializable] // 新增这一行即可 public class Message { public MessageType Type { get; set; } public string Content { get; set; } } public enum MessageType { Hello, Welcome, BookInquiry, UserInquiry, BookInquiryReply, UserInquiryReply, EndCommunication, Error, NotFound, }
添加序列化/反序列化工具方法:
// 对象转字节数组 public static byte[] SerializeObj(object obj) { using (MemoryStream ms = new MemoryStream()) { // 注意:.NET 5+默认禁用BinaryFormatter,需要在项目文件里加<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization> System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); formatter.Serialize(ms, obj); return ms.ToArray(); } } // 字节数组转对象 public static T DeserializeObj<T>(byte[] data) { using (MemoryStream ms = new MemoryStream(data)) { System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); return (T)formatter.Deserialize(ms); } }
发送时直接调用工具方法即可:
byte[] msgBytes = SerializeObj(message); // 同样建议先发长度再发内容,解决粘包问题 byte[] lenBytes = BitConverter.GetBytes(msgBytes.Length); clientSocket.Send(lenBytes); clientSocket.Send(msgBytes);
内容的提问来源于stack exchange,提问作者Poop poop
相关产品推荐
相关产品推荐

