Sending a 4-byte message header from a C # client to a Java server

I am trying to write a C # client to a server written in Java. The server expects a 4-byte (DataInputStread readInt () in Java) message header followed by the actual message.

I am completely new to C #, how can I send this message header to a Java server? I tried several methods (mainly trial and error, without delving too deeply into the C # language), and nothing worked. The Java side ended up with the wrong (very large) message length.

+7
java c # sockets
source share
6 answers

This, as indicated by other posters, to the end.

Java DataInputStream expects data to be big-endian (network byte order). Judging from the Mono documentation (for equivalents such as BinaryWriter ), C # tends to be of little significance (by default for Win32 / x86).

So, when you use the standard class library to change the 32-bit int '1' in bytes, they give different results:

//byte hex values Java: 00 00 00 01 C#: 01 00 00 00 

You can change the way ints are written in C #:

 private static void WriteInt(Stream stream, int n) { for(int i=3; i>=0; i--) { int shift = i * 8; //bits to shift byte b = (byte) (n >> shift); stream.WriteByte(b); } } 

EDIT:

A safer way to do this:

 private static void WriteToNetwork(System.IO.BinaryWriter stream, int n) { n = System.Net.IPAddress.HostToNetworkOrder(n); stream.Write(n); } 
+11
source share

It's simple, but have you checked the entity? This can easily be a mismatch between the content you sent the data to and the content you receive.

+2
source share

As already noted here, the problem is most likely caused by the fact that the C # application sends ints in little-endian order, while the Java application expects them in network order (big-endian). However, instead of explicitly reordering the bytes in a C # application, the correct way is to rely on built-in functions to convert from the host to the network order (htons and the like) - this way your code will continue to work fine even when running on a large machine.

In general, when resolving such problems, I find it useful to record the correct traffic (for example, Java in Java in your case) using tools such as netcat or wireshark, and then compare it with the wrong traffic to see where it goes wrong. As an added benefit, you can also use netcat to embed captured / prerecorded requests on the server or embed captured / prerecorded responses in the client. Not to mention the fact that you can also modify the requests / responses in the file and test the results before proceeding with the code correction.

+2
source share

If you are going to exchange a lot of data, I would recommend implementing (or finding) a Stream-wrapper that can write and read ints in network order. But if you really only need to write the length, do something like this:

 using(Socket socket = ...){ NetworkStream ns = new NetworkStream(socket); ns.WriteByte((size>>24) & 0xFF); ns.WriteByte((size>>16) & 0xFF); ns.WriteByte((size>>8) & 0xFF); ns.WriteByte( size & 0xFF); // write the actual message } 
+1
source share

I don't know C #, but you just need to do the equivalent of this:

 out.write((len >>> 24) & 0xFF); out.write((len >>> 16) & 0xFF); out.write((len >>> 8) & 0xFF); out.write((len >>> 0) & 0xFF); 
0
source share

The Sysetm.Net.IPAddress class has two static helper methods: HostToNetworkOrder () and NetworkToHostOrder (), which do the conversion for you. You can use it with a BinaryWriter over a stream to write the correct value:

 using (Socket socket = new Socket()) using (NetworkStream stream = new NetworkStream(socket)) using (BinaryWriter writer = new BinaryWriter(stream)) { int myValue = 42; writer.Write(IPAddress.HostToNetworkOrder(myValue)); } 
0
source share

All Articles