【问题标题】:Socket WriteLine/ReadLine getting mismatched套接字 WriteLine/ReadLine 不匹配
【发布时间】:2017-04-06 04:35:04
【问题描述】:

通常我能够自己解决问题,但我不得不再次寻求帮助。如果有些内容不连贯,我提前道歉,因为我似乎有点发烧。

我目前正在 XNA 中制作非常简单的游戏。这是一款 2D 高空射击游戏。唯一的动作是玩家射击子弹。问题是,我想让它成为多人游戏(同一网络中的玩家)。

我考虑过以下方法:

  1. 其中一个玩家托管服务器

    • 服务器保存每个玩家和子弹的位置信息
    • 服务器创建新世界(由玩家和子弹组成)并在新线程中更新它,如下所示:

      while (true)
          {
              lock (world) world.update();
              Thread.Sleep(worldUpdatePeriod);
          }
      
    • 服务器为每个需要处理的玩家创建新线程

  2. 玩家连接到服务器

    • 他们应该定期从服务器接收信息他们应该画什么:

      class Asset
      {
         string type;
         Vector2 position;
      }
      
    • 他们应该能够从键盘和鼠标发送输入来移动和射击。

现在,重点。播放器可以向服务器发送三种类型的消息:

  • “可以阅读”
  • “鼠标”
  • “键盘”

    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);
        }
    }
}

现在如果标题是,例如,“CAN READ”

  1. 服务器

    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;
    
  2. 客户

    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 类和 handleClient 类有单独的 streamReaders 和 streamWriters。

你明白了。我正在尝试将来自服务器的每个 WriteLine() 与来自客户端的 ReadLine() 等进行匹配。它工作正常!直到我将用户输入添加到混合物中。

一旦我发送键盘输入(如上所示匹配),它似乎可以工作,偶尔会出现 System.FormatException,这意味着某些 ReadLine() 读取错误的 WriteLine()。我能够抓住并重试。

一旦我发送鼠标输入,一切都会变得糟糕。不匹配的异常变得更频繁,以至于“游戏”无法进行。所以我想知道我的方法是否有问题。对于问题的长度,我深表歉意,我试图简洁,但也觉得需要提供上下文。谢谢,如果你坚持到最后,我很乐意回答任何进一步的问题,因为我在过去几天试图解决它。

【问题讨论】:

标签: c# multithreading xna tcpclient streamreader


【解决方案1】:

我已经阅读了 Andrew 提供给我的链接,并且我已经能够使它工作。如何?使用 TCP 客户端(建立连接,从客户端读取输入)和 UDP 客户端(向每个客户端广播资产)。只是发布,以防将来有人遇到这样的问题,我非常怀疑。

干杯!

【讨论】:

    猜你喜欢
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    • 1970-01-01
    • 2020-07-04
    • 2013-06-16
    • 2011-01-23
    • 1970-01-01
    相关资源
    最近更新 更多