這幾天在部落格園上看到好幾個寫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
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iMwEjN0YWNxEGNxQzYmVmZyYzX5ADO1ATM5EzLchDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
java的預設輸出,這裡使用的是netty的預設架構。進行的int4的位元組序輸出
高位和低位表示法完全不同。
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));