将数据从C#客户端发送到Java服务器-数据不一致。
我不确定这里的问题是什么,但我发送到Java的所有数据似乎都被破坏了。它在Java客户机上运行完全正常,我已经验证了两种语言之间每个原语的字节大小 我将从客户机的C#方面开始,因为我已经非常简单: 这是PacketBuilder类将数据从C#客户端发送到Java服务器-数据不一致。,java,c#,Java,C#,我不确定这里的问题是什么,但我发送到Java的所有数据似乎都被破坏了。它在Java客户机上运行完全正常,我已经验证了两种语言之间每个原语的字节大小 我将从客户机的C#方面开始,因为我已经非常简单: 这是PacketBuilder类 /// <summary> /// Used to build a instance of the <see cref="UnityNetworking.Packet"/> class. /// </summary>
/// <summary>
/// Used to build a instance of the <see cref="UnityNetworking.Packet"/> class.
/// </summary>
public class PacketBuilder {
/// <summary>
/// The opcode of the packet being built.
/// </summary>
private int Opcode;
/// <summary>
/// The stream to write data to the packet's buffer.
/// </summary>
private MemoryStream stream;
/// <summary>
/// The binary writer to convert data into binary format.
/// </summary>
private BinaryWriter writer;
/// <summary>
/// The String encoder.
/// </summary>
private Encoding encoder;
/// <summary>
/// Create a new PacketBuilder instance with the specified opcode and a default capacity.
/// </summary>
/// <param name="opcode">The opcode.</param>
public static PacketBuilder Create(int opcode) {
return new PacketBuilder (opcode, 512);
}
/// <summary>
/// Create a new PacketBuilder instance with the specified opcode and capacity.
/// </summary>
/// <param name="opcode">The opcode.</param>
/// <param name="capacity">The buffer capacity.</param>
public static PacketBuilder Create(int opcode, int capacity) {
return new PacketBuilder (opcode, capacity);
}
/// <summary>
/// Initializes a new instance of the <see cref="UnityNetworking.PacketBuilder"/> class.
/// </summary>
/// <remarks>Private scope to prevent outside library instantiation.</remarks>
private PacketBuilder (int opcode, int capactiy) {
Opcode = opcode;
stream = new MemoryStream (capactiy);
writer = new BinaryWriter (stream);
encoder = new UTF8Encoding (true, true);
}
/// <summary>
/// Adds the specified data to the builders buffer.
/// </summary>
/// <param name="data">The data.</param>
public PacketBuilder Add(object data) {
if (data is Int16) {
writer.Write ((short)data);
} else if (data is Int32) {
writer.Write ((int)data);
} else if (data is Int64) {
writer.Write ((long)data);
} else if (data is Single) {
writer.Write ((float)data);
} else if (data is Double) {
writer.Write ((double)data);
} else if (data is Byte) {
writer.Write ((byte)data);
} else if (data is Boolean) {
writer.Write ((bool)data);
} else if (data is String) {
string str = (string)data;
byte[] bytes = encoder.GetBytes (str);
writer.Write ((short)bytes.Length);
writer.Write (bytes, 0, bytes.Length);
} else {
throw new Exception ("Unsupported Object Type: " + data);
}
Debug.Log ("Data Type: " + data.GetType() + " || Value: " + data);
return this;
}
public Packet ToPacket() {
return new Packet(Opcode, stream.ToArray());
}
}
这是通过客户端类中的Write(Packet)
方法发送的,可在此处找到:
public NetworkClient Write(Packet packet) {
networkStream.Write (packet.Buffer, 0, packet.Size);
return this;
}
非常基本:现在在Java端,所有内容都被放入一个ByteBuffer
中,该数据是使用getX
方法获取的
我获取这些数据的方法如下:
public boolean handle(long userId, Session session, Packet packet) {
ByteBuffer buffer = packet.getBuffer();
byte opcode = buffer.get();
userId = buffer.getLong();
System.out.println("Opcode: " + opcode + " || User ID: " + userId);
}
这将输出以下行:
Opcode: 1 || User ID: 4108690235045445632
我一点也不明白到底发生了什么,尤其是1337怎么会变成只有上帝知道的数字。从客户端进行调试时,将显示以下信息:
Data Type: System.Byte || Value: 1
Data Type: System.Int64 || Value: 1337
所以,如果有人能告诉我发生了什么,那就太好了 您的64位整数有不同的字节顺序 您得到的值是1337L,即0x0539。如果反转此字节值,则得到0x3905000000000000。将其转换为十进制,得到4108690235045445632
通常,当通过网络发送原始数据(如数据包)时,您将使用lton(值)发送,以及ntol(值)发送您接收的值。我不确定C#和Java的等价物是什么,但它们是“长到网络”和“网络到长”函数。类似地,您可以对short和其他类型(8位值除外)执行此操作。BinaryWriter使用小端编码,而Java使用大端编码。这意味着
Int64
的最低有效字节首先用C#编写,Java解释具有最高有效字节的字节
在这里查看强制C端使用Big-Endian的方法:这可能是一个问题,具体取决于机器。我知道Java是big-endian,我认为Intel机器是little-endian。因此,如果您的C#程序运行在基于Intel的机器上,这可能是您的问题。Java在规范中使用big-endian,并
DataOutputStream
使用它。在Java中使用little endian需要额外的工作。C#不定义尾数,但BinaryWriter
使用很少的尾数。因此,在C#中使用big-endian需要额外的工作。@Icemandind-您可能打算对Op进行评论。是的,显然是Endianness问题。@Les-感谢您对反转字节值的说明,我已经解决了这个问题,现在我所有的网络都可以从客户端->服务器完美地工作。现在,我只需要从服务器->客户端反转这个过程。再次感谢。
Data Type: System.Byte || Value: 1
Data Type: System.Int64 || Value: 1337