天天看點

Java和C#的socket通信相關(轉)

這幾天在部落格園上看到好幾個寫Java和C#的socket通信的文章。但是都為指出其中關鍵點。

C# socket通信元件有很多,在vs 使用nuget搜尋socket元件有很多類似的。本人使用的是自己開發的一套元件。

Java socket通信的元件也有很多,常用的大多數都是用的mina或者netty。遊戲行業使用也是居多。

關于socket的底層寫法,實在太多,我就不在BB。

這裡我想說,C#和C++或者叫VC++把是使用小端序作為位元組序。而java使用的是大端序作為位元組序。

也就是說比如一個int占用四個位元組,java的位元組序和c#的位元組序是相反的,java的int四個位元組第一個位元組在數組的最後一個。C#是第一個。

也就是說如果java端正常發送一個int的位元組序給C#,需要翻轉一次端緒。反之也是一樣的。一句話來概括的話就是高位在前還是低位在前的問題。

C#輸出數字 int 4 的位元組序。為了保證c#下面絕對是是int是以加入了強制int轉化。預設的話可能是byte

Java和C#的socket通信相關(轉)

java的預設輸出,這裡使用的是netty的預設架構。進行的int4的位元組序輸出

Java和C#的socket通信相關(轉)

高位和低位表示法完全不同。

java下面如果傳輸字元串,那麼必須要先把字元串轉化成byte數組,然後擷取數組長度,在位元組序裡面壓入int表示的數組長度,然後在然如byte數組。不管你的字元串多長。

而C#也是相同做法。但是唯一不同的是數組的長度表示法不同。微軟經過了位元組壓縮的。用位元組的前7位表示長度。第8位表示下一個位元組是否也是表示長度的位元組,值需要與128位于。

進而減少位元組的消耗。

現在一般如果我們在java和C#中無論是哪一個語言作為伺服器。架設socket通信基準。其中另外一方都要妥協位元組序反轉問題。

大多數情況下我們也許通信的要求不高,或許把一些類或者參數通過json格式化以後傳輸給對方。但是在這一條消息的傳輸中,一般會有兩個int需要位元組序。最少也要一個位元組序。

一個位元組序int表示消息長度。另外一個位元組序表示消息協定。

如果消息協定都放到json裡面沒有問題。但是消息長度是必不可少的。因為你需要知道在網絡環境中,消息壓棧,然後等待系統發出是有可能兩條消息一同發送的。也或者消息發送後由于網絡阻塞,前後相差好幾秒的消息同一時間達到。

這就是所謂的粘包。

我這裡就不表演了。

還有另外一種通信方式,就是通過protobuf進行位元組序的序列化,和反序列,官方支援java,第三方支援C#。這個元件可以減少位元組流。達到省流量,減少網絡資源消耗的問題。

例如一個long的類型值是1正常發送需要8個位元組,64位。發送。如果改用protobuf的話隻需要1位元組8位就能發送。

同樣的問題,無論你使用哪一種序列化方式,都需要消息長度和消息協定号。

C#下面對int的反轉讀取。

/// <summary>
////// </summary>
/// <param name="value"></param>
public int ReadInt(byte[] intbytes)
return BitConverter.ToInt32(intbytes, 0);
10 
11         /// <summary>
12         ///13         /// </summary>
14         /// <param name="value"></param>
15         public byte[] WriterInt(int16 17             byte[] bs =18 19             return20         }      
usingusingusingusingusingusing/**

*/
namespace{
public classpublic enumpublicpublic static JavaOrNet JN =/// <summary>
////// </summary>
/// <param name="value"></param>
public int ReadInt(byte[] intbytes)
return BitConverter.ToInt32(intbytes, 0);
/// <summary>
////// </summary>
/// <param name="value"></param>
public byte[] WriterInt(intbyte[] bs =return//用于存儲剩餘未解析的位元組數
private List<byte> _LBuff = new List<byte>(2);
//位元組數常量一個消息id4個位元組
const long ConstLenght = 4L;
public voidthis.Dispose(true);
this);
protected virtual void Dispose(boolifthis._LBuff asif (disposable != null) { disposable.Dispose(); }
public byte[] Encoder(SocketMessage msg)
newnewbyte[] msgBuffer =if (msgBuffer != null)
switchcase4));
break;
case4));