套接字WriteLine / ReadLine不匹配

时间:2017-04-05 11:26:56

标签: c# multithreading xna tcpclient streamreader

通常我能够自己解决问题,但我必须再次寻求帮助。如果事情不连贯,我会事先道歉,因为看起来我有点发烧。

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

我考虑过以下方法:

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

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

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

  2. 玩家连接到服务器

    • 他们应定期从服务器接收信息:

      class Asset
      {
         string type;
         Vector2 position;
      }
      
    • 他们应该能够从键盘和鼠标发送输入以进行移动和拍摄。

  3. 现在,到了这一点。播放器能够向服务器发送三种类型的消息:

    • “CAN READ”
    • “MOUSE”
    • “键盘”

      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;
      }
      
    3. 当然,Client类和handleClient类具有单独的streamReaders nad streamWriters。

      你明白了。我试图将来自Server的每个WriteLine()与来自Client的ReadLine()进行匹配,依此类推。它工作正常!直到我向混合物添加用户输入。

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

      一旦我发送鼠标输入,一切都会变成地狱。不匹配的异常变得更加频繁到“游戏”无法播放的程度。所以我想知道我的方法是否有问题。我为问题的长度道歉,我试图简明扼要,但也觉得需要提供背景。谢谢,如果你把它做到最后,我很乐意回答任何进一步的问题,因为我试图在过去几天解决它。

1 个答案:

答案 0 :(得分:1)

我已经阅读了Andrew为我提供的链接,并且我已经能够使其工作。怎么样?使用TCP客户端(设置连接,从客户端读取输入)和UDP客户端(将资产广播到每个客户端)。只是张贴以防万一有人在将来遇到这样的问题,我非常怀疑。

干杯!