2008-09-18 7 views
7

Ich versuche, einen C# Client zu einem Server zu schreiben, die in Java geschrieben ist. Der Server erwartet einen 4 Byte (DataInputStread readInt() in Java) Nachrichtenkopf, gefolgt von der eigentlichen Nachricht.Senden einen 4-Byte-Nachrichtenkopf von C# Client zu einem Java Server

ich absolut bin neu in C#, wie kann ich diese Message-Header über an den Java-Server senden? Ich habe es auf verschiedene Arten versucht (meistens Trial-and-Error, ohne zu sehr in die C# -Sprache einzutauchen), und nichts hat funktioniert. Die Java-Seite endete mit der falschen (sehr großen) Nachrichtenlänge.

Antwort

2

Es ist einfach, aber haben Sie überprüft endianness? Es könnte leicht eine Abweichung zwischen dem endianness Ihnen die Daten gesendet haben und die Endian Sie in recieving sind

0

ich nicht C# wissen, aber Sie müssen nur das Äquivalent, dies zu tun.

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

Wenn Sie werden eine Menge Daten austauschen, ich würde empfehlen, einen Stream-Wrapper zu implementieren (oder zu finden), der Ints in Netzwerkreihenfolge schreiben und lesen kann. Aber wenn Sie wirklich brauchen nur die Länge tun, so etwas zu schreiben:

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 
} 
11

Es ist, wie andere Plakate haben darauf hingewiesen, bis auf endianness.

Das Java DataInputStream erwartet die Daten big-endian (Netzwerk-Byte-Reihenfolge). Gemessen an der Mono-Dokumentation (für Entsprechungen wie BinaryWriter) neigt C# dazu, Little-Endian zu sein (der Standard für Win32/x86).

Also, wenn Sie die Standard-Klassenbibliothek verwenden, um die 32-Bit-int zu ändern '1' Bytes, sie zu unterschiedlichen Ergebnissen führen:

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

Sie so, wie Sie Ints in C# schreiben verändern können:

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:

Ein sicherer Weg, dies zu tun wäre:

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

Wie jeder hier hat bereits darauf hingewiesen, ist das Problem höchstwahrscheinlich durch die C# Anwendung verursacht Ints in Little-Endian-Reihenfolge, während die Java-Anwendung erwartet, dass sie in Netzwerk Reihenfolge (Big-Endian) zu senden. Anstatt die Bytes in der C# -App explizit umzuordnen, müssen Sie jedoch auf integrierte Funktionen für die Konvertierung von Host- in Netzwerkreihenfolge (HTONs und Ähnliches) zurückgreifen. Auf diese Weise funktioniert Ihr Code auch bei der Ausführung einwandfrei auf einer Big-Endian-Maschine.

Im Allgemeinen finde ich es hilfreich, den richtigen Datenverkehr (z. B. Java zu Java in Ihrem Fall) mithilfe von Tools wie netcat oder wireshark aufzuzeichnen und dann mit dem falschen Verkehr zu vergleichen, um festzustellen, wo es sich befindet falsch machen. Als zusätzlichen Vorteil können Sie netcat auch verwenden, um erfasste/voraufgezeichnete Anforderungen in den Server zu injizieren oder erfasste/voraufgezeichnete Antworten in den Client zu injizieren. Ganz zu schweigen davon, dass Sie auch die Anfragen/Antworten in einer Datei ändern und die Ergebnisse testen können, bevor Sie mit der Korrektur des Codes beginnen.

0

Die Klasse Sysetm.Net.IPAddress verfügt über zwei statische Hilfsmethoden: HostToNetworkOrder() und NetworkToHostOrder(), die die Konvertierung für Sie durchführen. Sie können es mit einem Binary über den Strom verwenden Sie den richtigen Wert zu schreiben:

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)); 
}