我有一个学校项目,我正在使用TCPClient-Server在LAN上制作一个基于回合的RPG。到目前为止,我已经能够通过序列化和反序列化对象从两个客户端将其选择的类发送到服务器,但现在我在将玩家 2 角色发送到玩家 1 客户端时遇到问题(玩家 1 充当主机,服务器程序在该计算机中运行)。
客户端代码
//part where I send the character to the server
byte[] player;
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, Player);
player = ms.ToArray();
byte[] DLen = BitConverter.GetBytes((Int32)player.Length);
netstream = Cliente.GetStream();
netstream.Write(DLen, 0, 4);
netstream.Write(player, 0, player.Length);
netstream.Flush();
ms.Flush();
//part where I receive the other client's character from the server
byte[] DataLength = new byte[4];
netstream = Cliente.GetStream();
netstream.Read(DataLength, 0, 4);//<----HOST Client "skips" this line (executes instruction BEFORE Reset Event was notified in server side)
int length = BitConverter.ToInt32(DataLength, 0);
player = new byte[length];
netstream.Read(player, 0, length);
ms = new MemoryStream(player);
bf = new BinaryFormatter();
ms.Position = 0;
object ob = bf.Deserialize(ms);//<----Line where exception appears ONLY on HOST Client
CPU = (ACharacter)ob;
netstream.Flush();
服务器代码
AutoResetEv.WaitOne();//<---Waits until BOTH players have selected their characters
//Begin sending to P2
byte[] player;
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, Player1);
player = ms.ToArray();
byte[] DataLength = BitConverter.GetBytes((Int32)player.Length);
netstream = Jug2Sock.GetStream();
netstream.Write(DataLength, 0, 4);
netstream.Write(player, 0, player.Length);
netstream.Flush();
//Finished sending to P2
//Begin sending to P1
ms = new MemoryStream();
bf = new BinaryFormatter();
bf.Serialize(ms, Player2);
player = ms.ToArray();
DataLength = BitConverter.GetBytes((Int32)player.Length);
netstream = Jug1Sock.GetStream();
netstream.Write(DataLength, 0, 4);
netstream.Write(player, 0, player.Length);
netstream.Flush();
//Finished sending to P1
我真的不知道这里有什么问题,因为玩家 1 的角色使用相同的代码正确发送到玩家 2,但我注意到由于某种原因,在 P1 的客户端中读取数据长度的行被"跳过"。我的意思是说客户端 1 只是在服务器发送数据之前执行指令(服务器被 AutoResetEvent 搁置以控制它)。
非常感谢您的帮助。
我认为您需要处理读取操作返回的读取字节数
netstream = Cliente.GetStream();
int numBytesToRead = 4;
do
{
// Read may return anything from 0 to 4.
int n = netstream.Read(DataLength, numBytesRead, numBytesToRead);
numBytesRead += n;
numBytesToRead -= n;
} while (numBytesToRead > 0);
int length = BitConverter.ToInt32(DataLength, 0);
这是如何处理前 4 个字节(包含 DataLength)的读取的示例。读取玩家数据可以像这样完成:
player = new byte[length];
numBytesRead = 0;
numBytesToRead = length;
do
{
int n = netstream.Read(player, numBytesRead, numBytesToRead);
numBytesRead += n;
numBytesToRead -= n;
} while (numBytesToRead > 0);
ms = new MemoryStream(player);