2012-01-19 51 views
3

我一直在为这一整天而战。我需要在C#服务器和Java客户端之间发送字符串(JSON)。我必须将前4个字节(总是4个字节)作为消息的长度(头部,这样我们知道消息的剩余时间),然后是消息的正文。流在应用程序的整个生命周期内保持打开状态。就我个人而言,我只是用'\ n'分隔每条消息,然后使用readLine(),但客户端需要这样。在c#和java套接字之间读取和写入数据

我需要C#端发送和接收这些消息以及Java端。不太确定如何编码和解码所有内容。

一些我一直在玩的位:

C#发送

byte[] body = Encoding.ASCII.GetBytes(message); 
byte[] header = BitConverter.GetBytes((long) body.Length); 

foreach (byte t in header) 
{ 
    networkStream.WriteByte(t); 
} 


foreach (byte t in body) 
{ 
    networkStream.WriteByte(t); 
} 

我没有得到C#接收呢。 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); 

我知道代码是不是所有的完整的,但任何人都可以提供任何帮助?

+0

我会在C#上使用TextReader和StreamWriter。很容易,你可以直接用字符串写和读消息。 – weismat

+0

正如我所说,我没有选择。我必须发送前4个字节作为消息的长度。 – Dylan

回答

4

使用'\n'分隔邮件不是一个好主意,除非您确定您的邮件只包含单行文本。如果一个'\n'天生出现在您的一条消息中,那么该消息就会分裂。

您声明消息长度必须完全是4个字节;然而,下面的行产生一个8字节的数组:

byte[] header = BitConverter.GetBytes((long) body.Length); 

其原因是,在C#,long是用于Int64结构的别名,代表一个64位带符号整数。您需要的是一个intuint,它表示一个32位有符号或无符号整数。因此,只要改变上述行:

byte[] header = BitConverter.GetBytes(body.Length); 

你需要做的另一个重要的考虑因素是数据的endianness。想象一下,你正试图创建一个4字节的数组,例如7的值。在一个大端平台上,这将被编码为0,0,0,7;在小端平台上,它将被编码为7,0,0,0。然而,如果它得到具有相反端序的平台上解码时,7将被解释为最显著字节,给人117440512的值(等于7×256 3 ),而不是7.

因此,您的Java和C#应用程序的字节顺序必须为。 Java ByteBuffer默认为big-endian;但是,C#BitConverter是依赖于体系结构的,可以通过其IsLittleEndian静态属性进行检查。您可以让C#始终遵循大端排列规则,通过在小端时颠倒数组:

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