在c#和java套接字之间读取和写入数据

在c#和java套接字之间读取和写入数据,c#,java,string,sockets,bytearray,C#,Java,String,Sockets,Bytearray,我一整天都在为这个争吵。我需要在C#服务器和Java客户端之间发送字符串(JSON)。我必须将前4个字节(始终为4个字节)作为消息的长度(标头,这样我们就知道消息的其余部分有多长),然后是消息的正文。流在应用程序的生命周期内保持打开状态。就我个人而言,我会用“\n”分隔每条消息,然后使用readLine(),但客户端需要这样做 我需要C端和Java端发送和接收这些消息。不太确定如何编码和解码一切 我一直在玩的一些东西: 发送 我还没拿到C#receive。Java发送: byte[] dataT

我一整天都在为这个争吵。我需要在C#服务器和Java客户端之间发送字符串(JSON)。我必须将前4个字节(始终为4个字节)作为消息的长度(标头,这样我们就知道消息的其余部分有多长),然后是消息的正文。流在应用程序的生命周期内保持打开状态。就我个人而言,我会用“\n”分隔每条消息,然后使用readLine(),但客户端需要这样做

我需要C端和Java端发送和接收这些消息。不太确定如何编码和解码一切

我一直在玩的一些东西:

发送

我还没拿到C#receive。Java发送:

byte[] dataToSend = data.getBytes();
byte[] header = ByteBuffer.allocate(4).putInt(dataToSend.length).array();
ByteArrayOutputStream output = new ByteArrayOutputStream();
output.write(header);
output.write(dataToSend);
output.writeTo(outputStream);
Java接收:

byte[] header = new byte[4];
int bytesRead;
do {
    Debug.log("TCPClient- waiting for header...");
    bytesRead = reader.read(header);

    ByteBuffer bb = ByteBuffer.wrap(header);
    int messageLength = bb.getInt();

    Debug.log("TCPClient- header read. message length (" + messageLength + ")");

    byte[] body = new byte[messageLength];
    do {
       bytesRead = reader.read(body);
    }
    while (reader.available() > 0 && bytesRead != -1);
}
while (reader.available() > 0 && bytesRead != -1);

我知道代码不完整,但有人能提供帮助吗?

'\n'
分隔消息不是一个好主意,除非您确定您的消息将只包含单行文本。如果一个
'\n'
内在地出现在您的一封邮件中,那么该邮件将被拆分

您声明消息长度必须正好为4字节;但是,以下行生成一个8字节数组:

byte[] header = BitConverter.GetBytes((long) body.Length);
原因是,在C#中,
long
Int64
结构的别名,表示64位有符号整数。您需要的是一个表示32位有符号或无符号整数的
int
uint
。因此,只需将上述行更改为:

byte[] header = BitConverter.GetBytes(body.Length);
您需要考虑的另一个重要因素是数据的完整性。假设您正试图创建一个4字节数组,其值为7。在big-endian平台上,这将被编码为
0,0,0,7
;在一个小小的endian平台上,它将被编码为
7,0,0,0
。但是,如果在具有反向端性的平台上对其进行解码,
7
将被解释为最高有效字节,给出的值为117440512(等于7×2563),而不是7

因此,Java和C#应用程序的endianness必须相同。默认情况下,Java是big-endian;但是,C#依赖于体系结构,可以通过其静态属性进行检查。通过在数组为小端时反转数组,可以使C#始终遵循大端惯例:

byte[] header = BitConverter.GetBytes(body.Length);
if (BitConverter.IsLittleEndian)
    Array.Reverse(header);

我会在C#上使用文本阅读器和流式编写器。简单多了,你可以直接用字符串写和读消息。正如我所说,我没有选择。我必须发送前4个字节作为消息的长度。
byte[] header = BitConverter.GetBytes(body.Length);
if (BitConverter.IsLittleEndian)
    Array.Reverse(header);