套接字 WriteLine/ReadLine 不匹配
Socket WriteLine/ReadLine getting mismatched
平时遇到问题自己能解决,但又不得不求助。如果有什么不连贯的地方,我提前道歉,因为我好像有点发烧。
我目前正在使用 XNA 制作非常简单的游戏。这是一款 2D 高空射击游戏。唯一的动作是玩家射击子弹。问题是,我想让它成为多人游戏(同一网络中的玩家)。
我考虑过以下方法:
其中一位玩家托管服务器
- 服务器保存每个玩家和子弹的位置信息
服务器创建新世界(由玩家和子弹组成)并像这样在新线程中更新它:
while (true)
{
lock (world) world.update();
Thread.Sleep(worldUpdatePeriod);
}
服务器为每个必须处理的玩家创建新线程
玩家连接服务器
他们应该定期从服务器接收信息他们应该画什么:
class Asset
{
string type;
Vector2 position;
}
他们应该能够从键盘和鼠标发送输入来移动和射击。
现在,进入正题。播放器可以向服务器发送三种类型的消息:
- "CAN READ"
- "MOUSE"
"KEYBOARD"
string header = "CAN READ";
lock (streamWriter) { streamWriter.WriteLine(header); }
服务器,在每个客户端的单独线程中等待消息
streamReader = new StreamReader(networkStream);
streamWriter = new StreamWriter(networkStream);
streamWriter.AutoFlush = true;
while (true)
{
if (networkStream.DataAvailable)
{
string header;
lock (streamReader)
{
header = Convert.ToString(streamReader.ReadLine());
Console.WriteLine($"Header received: {header}");
handleHeader(header);
}
}
}
现在如果 header 是,例如 "CAN READ"
服务器
case "CAN READ":
if (streamWriter.BaseStream.CanRead)
{
lock (streamWriter)
{
streamWriter.WriteLine(server.world.assets.Count);
foreach (var asset in server.world.assets)
{
streamWriter.WriteLine(asset.type);
streamWriter.WriteLine(asset.position.X);
streamWriter.WriteLine(asset.position.Y);
}
}
}
break;
客户
int assetCount = Convert.ToInt32(streamReader.ReadLine());
List<Asset> receivedAssets = new List<Asset>();
lock (streamReader)
{
for (int i = 0; i < assetCount; i++)
{
string type = Convert.ToString(streamReader.ReadLine());
int x = Convert.ToInt32(streamReader.ReadLine());
int y = Convert.ToInt32(streamReader.ReadLine());
receivedAssets.Add(new Asset(type, new Vector2(x, y)));
}
return receivedAssets;
}
当然,Client class 和 handleClient class 有独立的 streamReaders 和 streamWriters。
你懂的。我正在尝试将来自服务器的每个 WriteLine() 与来自客户端的 ReadLine() 进行匹配,依此类推。而且效果很好!直到我将用户输入添加到混合物中。
一旦我发送键盘输入(如上所示匹配),它似乎可以工作,偶尔 System.FormatException,这意味着某些 ReadLine() 读错了 WriteLine()。我能够抓住它并重试。
一旦我也发送鼠标输入,一切都会变得糟糕。不匹配的异常更常见到 'game' 无法播放的地步。所以我想知道我的方法是否有问题。对于问题的长度,我深表歉意,我尽量简洁,但也觉得有必要提供上下文。谢谢,如果你能坚持到最后,我很乐意回答任何进一步的问题,因为我在过去几天一直在努力解决它。
我已经阅读了 Andrew 提供给我的 link,我已经能够让它发挥作用。如何?同时使用 TCP 客户端(建立连接,从客户端读取输入)和 UDP 客户端(向每个客户端广播资产)。只是发布以防将来有人遇到此类问题,我对此表示高度怀疑。
干杯!
平时遇到问题自己能解决,但又不得不求助。如果有什么不连贯的地方,我提前道歉,因为我好像有点发烧。
我目前正在使用 XNA 制作非常简单的游戏。这是一款 2D 高空射击游戏。唯一的动作是玩家射击子弹。问题是,我想让它成为多人游戏(同一网络中的玩家)。
我考虑过以下方法:
其中一位玩家托管服务器
- 服务器保存每个玩家和子弹的位置信息
服务器创建新世界(由玩家和子弹组成)并像这样在新线程中更新它:
while (true) { lock (world) world.update(); Thread.Sleep(worldUpdatePeriod); }
服务器为每个必须处理的玩家创建新线程
玩家连接服务器
他们应该定期从服务器接收信息他们应该画什么:
class Asset { string type; Vector2 position; }
他们应该能够从键盘和鼠标发送输入来移动和射击。
现在,进入正题。播放器可以向服务器发送三种类型的消息:
- "CAN READ"
- "MOUSE"
"KEYBOARD"
string header = "CAN READ"; lock (streamWriter) { streamWriter.WriteLine(header); }
服务器,在每个客户端的单独线程中等待消息
streamReader = new StreamReader(networkStream);
streamWriter = new StreamWriter(networkStream);
streamWriter.AutoFlush = true;
while (true)
{
if (networkStream.DataAvailable)
{
string header;
lock (streamReader)
{
header = Convert.ToString(streamReader.ReadLine());
Console.WriteLine($"Header received: {header}");
handleHeader(header);
}
}
}
现在如果 header 是,例如 "CAN READ"
服务器
case "CAN READ": if (streamWriter.BaseStream.CanRead) { lock (streamWriter) { streamWriter.WriteLine(server.world.assets.Count); foreach (var asset in server.world.assets) { streamWriter.WriteLine(asset.type); streamWriter.WriteLine(asset.position.X); streamWriter.WriteLine(asset.position.Y); } } } break;
客户
int assetCount = Convert.ToInt32(streamReader.ReadLine()); List<Asset> receivedAssets = new List<Asset>(); lock (streamReader) { for (int i = 0; i < assetCount; i++) { string type = Convert.ToString(streamReader.ReadLine()); int x = Convert.ToInt32(streamReader.ReadLine()); int y = Convert.ToInt32(streamReader.ReadLine()); receivedAssets.Add(new Asset(type, new Vector2(x, y))); } return receivedAssets; }
当然,Client class 和 handleClient class 有独立的 streamReaders 和 streamWriters。
你懂的。我正在尝试将来自服务器的每个 WriteLine() 与来自客户端的 ReadLine() 进行匹配,依此类推。而且效果很好!直到我将用户输入添加到混合物中。
一旦我发送键盘输入(如上所示匹配),它似乎可以工作,偶尔 System.FormatException,这意味着某些 ReadLine() 读错了 WriteLine()。我能够抓住它并重试。
一旦我也发送鼠标输入,一切都会变得糟糕。不匹配的异常更常见到 'game' 无法播放的地步。所以我想知道我的方法是否有问题。对于问题的长度,我深表歉意,我尽量简洁,但也觉得有必要提供上下文。谢谢,如果你能坚持到最后,我很乐意回答任何进一步的问题,因为我在过去几天一直在努力解决它。
我已经阅读了 Andrew 提供给我的 link,我已经能够让它发挥作用。如何?同时使用 TCP 客户端(建立连接,从客户端读取输入)和 UDP 客户端(向每个客户端广播资产)。只是发布以防将来有人遇到此类问题,我对此表示高度怀疑。
干杯!