2008-09-18 22 views
7

C# istemciden bir 4 bayt mesajı başlığını gönderme. Sunucu, gerçek iletinin ardından 4 bayt (Java'da DataInputStread readInt()) ileti üstbilgisi bekler. Java Server üzerinden bu mesaj başlığı gönderir nasıl C# için kesinlikle yeni duyuyorumJava ile yazılmış bir sunucuya bir C# istemci yazmaya çalışıyorum bir Java Sunucu

? Birkaç yolu denedim (çoğunlukla C# diline çok fazla girmeden deneme ve yanılma) ve hiçbir şey işe yaramadı. Java tarafı yanlış (çok büyük) mesaj uzunluğu ile bitti.

cevap

2

Çok basit ama endianness'ın kontrol ettikten? Kolayca içeri veri gönderdiyseniz endian ve içinde recieving olan endian arasında bir uyumsuzluk olabilir

0

C# bilmiyorum ama sadece bu eşdeğer yapmak gerekir.

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

ise Çok fazla veri alışverişinde bulunacaksınız, ağ düzeninde ints yazı yazabilen ve okuyabilecek bir Stream-wrapper uygulamanızı (veya bulmayı) tavsiye ederim. Diğer posterleri belirttiğimiz gibi endian aşağı,

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

Öyle: Ama gerçekten sadece uzunluğunu yazmak gerekirse böyle bir şey yapmak.

Java DataInputStream veri big-endian (ağ bayt sırası) olmasını bekler. Mono belgelerinden (BinaryWriter gibi eşdeğerler için) C#, küçük endian olma eğilimindedir (Win32/x86 için varsayılan).

Eğer 32bit int '1' bayt değiştirmek için standart sınıf kitaplığı kullandığınızda

Yani, bunlar farklı sonuçlar:

: Sen C# int'leri yazmak şekilde değiştirebilir

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

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

DÜZENLEME:

bunu yapmanın daha kolay yolu olacaktır:

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

burada zaten sorun büyük olasılıkla Java uygulaması ağ siparişi (big-endian) onları beklediğini ise küçük endian sırayla int'leri gönderen C# uygulaması neden olur, işaret etmiştir. Ancak, C# uygulamasında açık bir şekilde baytları yeniden düzenlemek yerine, doğru yol ana bilgisayardan ağ sırasına (htons ve benzerleri) dönüştürmek için yerleşik işlevlere güvenmektir - bu şekilde kodunuz çalıştırıldığında bile düzgün çalışmaya devam edecektir. Büyük bir endian makinede.

Genel olarak, bu tür sorunları giderirken, netcat ya da wireshark gibi araçları kullanarak doğru trafiği (örneğin, Java'yı Java'yı kullanarak) kaydetmeyi ve sonra onu nerede olduğunu görmek için yanlış trafiğe göre karşılaştırmanızı yararlı buluyorum. yanlış gidiyor. Ek bir avantaj olarak, yakalanan/önceden kaydedilmiş istekleri sunucuya enjekte etmek veya istemcide yakalanan/önceden kaydedilmiş yanıtları enjekte etmek için netcat'i de kullanabilirsiniz. Ayrıca bir dosyadaki istekleri/yanıtları değiştirebileceğinizi ve kodun düzeltilmesiyle başlamadan önce sonuçların test edilebileceğini belirtmemek.

0

Sysetm.Net.IPAddress sınıfının iki statik yardımcı yöntemi vardır: HostToNetworkOrder() ve sizin için dönüşümü yapan NetworkToHostOrder(). Uygun değeri yazmak için akış üzerinde bir BinaryWriter ile kullanabilirsiniz:

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)); 
} 
İlgili konular