我想通过服务器将 InkCanvas 笔画发送到其他客户端。
即使我用谷歌搜索也找不到任何提示。
- 客户端将数据包发送到服务器。
- 服务器将从客户端接收的数据包发送到其他客户端。
- 其他客户端将从服务器接收的数据包转换为 StrokeCollection 类型。
客户端代码
public void SendInkCanvas(int roomID, InkCanvas inkCanvas) { try { MemoryStream memoryStream = new MemoryStream(); inkCanvas.Strokes.Save(memoryStream); memoryStream.Position = 0; memoryStream.Flush(); Packet packet = new Packet(PacketType.SendInkCanvas, id); packet.data.Add("RoomID", roomID); packet.data.Add("Strokes", memoryStream); socket.Send(packet.ToBytes()); } catch (Exception e) { Debug.WriteLine(e.Message); } }
服务器代码
case PacketType.SendInkCanvas: int roomIDIC = (int)packet.data["RoomID"]; packet.senderID = ""; packet.data.Remove("RoomID"); // Dictionary<int, Dictionary<string, Socket>> roomClient foreach (Socket cli in roomClient[roomIDIC].Values) cli.Send(packet.ToBytes()); break;
其他客户端代码
DrawInkCanvas.Strokes = new StrokeCollection((MemoryStream)packet.data["Strokes"]);
数据包类
[Serializable] public class Packet { #region Variable public Dictionary<string, object> data; public int packetInt; public bool packetBool; public string senderID; public PacketType packetType; #endregion #region PacketType, SenderID public Packet(PacketType type, string senderID) { data = new Dictionary<string, object>(); this.packetType = type; this.senderID = senderID; } #endregion #region PacketBytes public Packet(byte[] packetBytes) { BinaryFormatter formatter = new BinaryFormatter(); MemoryStream stream = new MemoryStream(packetBytes); formatter.Binder = new AllowAllAssemblyVersionsDeserializationBinder(); formatter.AssemblyFormat = FormatterAssemblyStyle.Simple; Packet packet = (Packet)formatter.Deserialize(stream); stream.Close(); this.data = packet.data; this.packetInt = packet.packetInt; this.packetBool = packet.packetBool; this.senderID = packet.senderID; this.packetType = packet.packetType; } #endregion #region Packet To Bytes public byte[] ToBytes() { BinaryFormatter formatter = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); formatter.AssemblyFormat = FormatterAssemblyStyle.Simple; formatter.Serialize(stream, this); byte[] bytes = stream.ToArray(); stream.Close(); return bytes; } #endregion } #region PacketType public enum PacketType { SendInkCanvas } #endregion
问题是您正在尝试发送实际MemoryStream
。
MemoryStream
是一种引用类型,这意味着其他对象仅被赋予对应用程序内存中MemoryStream
地址的引用,而不是被赋予它们自己的整个对象副本。
当你执行packet.data.Add("Strokes", memoryStream);
时,从技术上讲,添加到字典中的是MemoryStream
对象的地址。因此,当您ToBytes()
并序列化Packet
(以及随之而来的data
字段(时,只会序列化MemoryStream
的内存地址,而不是实际内容。反序列化Packet
时,无法从新上下文访问现有MemoryStream
。
相反,您要做的是将MemoryStream
的内容添加到Packet
。为此,请将MemoryStream
写入Byte
数组,然后将其添加到data
数组中。Byte
是值类型,而不是引用类型,因此它的整个值被复制到data
中,并将随之序列化。