RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1242590
Accepted
iiKuzmychov
iiKuzmychov
Asked:2022-02-11 08:10:05 +0000 UTC2022-02-11 08:10:05 +0000 UTC 2022-02-11 08:10:05 +0000 UTC

C# 无法正确解析数据。TCP客户端。字节集。我的世界协议

  • 772

Minecraft 有自己的协议。我正在尝试实现客户端。我的世界版本 1.16.5

我请求你花点时间阅读这里写的所有内容,深入研究它,并尝试复制它。我将不胜感激!

协议的本质是客户端和服务器通过TCP协议进行通信,交换数据包。正如协议中所写,我的世界中的数据包是一组字节,由以下部分组成:数据包字节的长度、前缀和内容。(服务器,可本地一键启动,可在此处下载)

示例:要告诉服务器您是新客户端,您需要发送握手请求,其中包括номер протокола(在 minecraft 版本 1.16.5 上为 754)хост、порт和статус(= 2 用于授权)。

在代码中,它看起来像这样(为了简化再现和准确性,我删除了所有将值转换为字节的辅助类,反之亦然):

var packetLength    = new byte[] { 16 };            // длина пакета
var prefix          = new byte[] { 0x00 };          // префикс [1 байт]
var protocolVersion = new byte[] { 242, 5 };        // протокол (= 754) [2 байта]
var hostBytesLength = new byte[] { 9 };             // длина байтов хоста [1 байт]
var hostBytes       = new byte[] { 108, 11, 99,     // хост (= "localhost") [9 байт]
                                  97, 108, 104,
                                  11, 115, 116 };   
var port            = new byte[] { 221, 99 };       // порт (= 25565) [2 байта]
var nextState       = new byte[] { 2 };             // состояние [1 байт]

// stream = client.GetStream(), где client = new TcpClient("localhost", 25565)
stream.Write(packetLength,    0, packetLength.Length);
stream.Write(prefix,          0, prefix.Length);
stream.Write(protocolVersion, 0, protocolVersion.Length);
stream.Write(hostBytesLength, 0, hostBytesLength.Length);
stream.Write(hostBytes,       0, hostBytes.Length);
stream.Write(port,            0, port.Length);
stream.Write(nextState,       0, nextState.Length);

之后,服务器发送响应0x03:

// № байта  // значение // описание
[0]         3           длина пакета
[1]         0x03        префикс
[2-3]       128, 2      threshold - максимальный размер пакета (= 256)

上面的一切都很好。我的包裹正确离开,正确的包裹到达。问题在于服务器对我的下一个请求的响应——授权请求。

授权请求仅包括имя игрока. 所以请求本身:

var packetLength        = new byte[] { 6 };     // длина пакета
var prefix              = new byte[] { 0x00 };  // префикс [1 байт]
var usernameBytesLength = new byte[] { 4 };     // длина байтов имени игрока [1 байт]
var usernameBytes       = new byte[] { 98, 111, // имя игрока (= "bot2") [4 байта]
                                       116, 50 };

stream.Write(packetLength,        0, packetLength.Length);
stream.Write(prefix,              0, prefix.Length);
stream.Write(usernameBytesLength, 0, usernameBytesLength.Length);
stream.Write(usernameBytes,       0, usernameBytes.Length);

作为回应,我得到以下信息:

// № байта  // значение // описание
[0]         23          длина пакета
[1]         0x00        префикс
[2]         0x02        
[3-23]      байты       остальные данные

出了点问题。我应该在响应中收到一个数据包0x02,其中包含16-ти значный uuid和имя игрока,与请求中的相同。此外,与服务器返回的字节匹配的其他 0x00 数据包在 Wikipedia 上也没有描述。

我试图忽略这个零字节(读取,但不考虑),然后一切都一起增长:

// № байта  // значение // описание
[0]         23          длина пакета
[1]         0x00        что-то (проигнорированно)
[2]         0x02        префикс
[3-18]      байты       uuid
[19]        4           длина байтов имени игрока
[20-23]     98, 111,    имя игрока (= "bot2")
            116, 50

问题:为什么服务器没有在命中时发送这个空字节?

附言

我试过的:

  • 最初,我认为数据包长度始终为 1 字节,但后来我在 Wikipedia 上看到这是VarInt 1-3 bytes。VarInt 的特点是自动长度检测。然而,阅读new byte { 0x00, 0x02 }后,他认为0x00——这就是最终的价值。所以这个选项不可用。
  • 同步读取流,因为它假定数据没有时间读取或读取不正确
  • 更改 minecraft 版本(然后需要传输相应的协议号)
c#
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    iiKuzmychov
    2022-02-13T04:09:54Z2022-02-13T04:09:54Z

    我在协议中找到了对此的描述。这个晦涩的字节表示“打包”字节包的长度(0 - 未打包):

    在此处输入图像描述

    • 1

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5