Lex*_*ebb 0 c# java sockets byte
如果这个问题的标题不清楚,我道歉,但我无法找出用这么少的话来描述我的困境的最好方法.
我正在使用套接字和逐字节传输信息在java和C#之间编写通信框架.
我遇到了一个让我困惑几个小时的问题.正如你所希望的那样.java的字节基类型是有符号的,这意味着如果你以整数形式表示它,它可以存储-128到+127.但是,C#使用无符号字节,这意味着它以整数形式存储0-255.
这是我遇到这个问题的地方.如果需要从我的c#客户端向我的java服务器发送一些字节的信息,我使用以下代码:
C#:
MemoryStream stream;
public void write(byte[] b, int off, int len) {
stream.Write(b, off, len);
}
Run Code Online (Sandbox Code Playgroud)
Java的:
DataInputStream in;
public int read(byte[] b, int off, int len) throws IOException{
in.read(b, off, len));
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这些代码非常相似,在其自己的语言中使用时将产生可预测的结果.但是,由于签名的不同,这些将产生无法使用的数据.
即如果我从我的c#客户端发送255到java服务器,我将在java服务器上收到值-1.这是因为这两个值都由这8位表示:11111111
最好是为了解决这个问题,我需要使用以下代码,使用sbytec#的有符号字节.
C#:
MemoryStream stream;
public void write(sbyte[] b, int off, int len) {
//Code to change sbyte into a byte but keeping it in the form in which java will understand
stream.Write(b, off, len);
}
Run Code Online (Sandbox Code Playgroud)
我基本上需要在无符号C#字节内存储java的有符号字节表示,以便将该字节发送到服务器.我还需要反向执行此操作以从我的java服务器接收到的字节中获取sbyte.
我尝试了很多方法来做到这一点但没有成功.如果有人知道我怎么能这样做,我将非常感激.
你基本上不需要做任何事情,除了不再考虑字节作为数字.将它们视为8位,Java和C#是相同的.很少有人真的想将字节视为一个幅度 - 它通常只是二进制数据,如图像,或者可能是编码文本.
如果要将字节10100011从Java发送到C#或反之,请以最自然的方式进行.这些位是正确的,即使将它们视为数字时字节值也会不同.
目前还不完全清楚你实际尝试传播的数据,但在99.9%的情况下,你可以将其byte[]视为不透明的二进制数据,并且无需担心就可以传输它.
如果确实需要将字节视为大小,则需要确定所需的范围.处理Java范围更容易,因为C#可以支持它sbyte[]...但是如果你想要范围0-255,你只需要在Java端转换byte为a int并用最后8位掩盖它:
byte b = ...;
int unsigned = b & 0xff;
Run Code Online (Sandbox Code Playgroud)
如果你真的需要在C#上对待byte[],sbyte[]反之亦然,你可以使用一点秘密:即使C#不允许你在两者之间进行转换,CLR也可以.您需要做的就是通过转换引用来object欺骗C#编译器,使其认为它可能有效 - 否则它认为它最了解.所以这执行没有例外:
byte[] x = new byte[] { 255 };
sbyte[] y = (sbyte[]) (object) x;
Console.WriteLine(y[0]); // -1
Run Code Online (Sandbox Code Playgroud)
您可以以完全相同的方式转换到另一个方向.