兩個平台互相通信,對方發送數據過來,我方接收數據,對數據進行處理後發送結果給對方,對方進行相應的操作。
提取實際有效數據:
[] arrNew = , arrNew, , arrLen);
在對接收到的數據arrNew進行業務處理之後,將結果arrResult返回給對方,最後關閉連接:
socket.Close();
對上面代碼進行講解:首先,socket.Accept();這個方法,服務會一直停留在這個方法上面,等待客戶端的連接,一有客戶端連接上來,才會繼續執行下面的代碼。如果沒有客戶端來連接服務,程序將會一直停留在這個地方,會出現“假死”的現象。其次,上面的代碼示例只能處理一個客戶端的連接請求,請求處理完成後,就會關閉連接。服務端應該是一個永不會停止的程序,能夠一直監聽客戶端的請求,並對其進行處理和回饋。
所以對上面的問題進行說明,首先使用線程,開啟服務後,服務端處理監聽狀態,當有客戶端連接請求上來後,為該客戶端連接新創建一個線程,專門來處理該客戶端的請求操作。當有多個客戶端連接上來後,服務會為每個客戶端都新創建線程來處理。這樣服務可以繼續監聽其他客戶端的連接請求,一邊又可以對已連接上來的客戶端進行響應處理。其次,要服務隊能夠永遠的監聽客戶端的連接請求,就必須讓服務端在處理完一個客戶端的連接請求後,能夠繼續調用socket.Accept()來監聽連接請求,這裡使用while(true){}無限循環來實現。
isListener = =[] arrMsg = [ * arrLen =[] arrNew = , arrNew, =
由於本次需求上只有一個客戶端,所以這次沒有采用多線程的方式。只是在主線程上,新建一條線程專門用來監聽和處理客戶端的請求操作,這樣主線程還可以繼續執行它的任務,程序也不會出現“假死”的狀態。
當然,對於客戶端發送過來的數據,服務端要能進行識別判斷,提取有效數據。所以在本次雙方通信過程中,對數據的格式進行了約定,只有遵循了格式的數據才會進行處理解析和響應。接口協議定義如下表所示(數據協議XML結構定義省略):
通訊數據包結構定義如表下: 包頭標記 總長 消息類型 XML流長度 XML格式數據 包尾標記 4B 4B 1B 4B 2B數據包內各項目定義說明如下表: 序號 項目名稱 取值 說明 1 包頭 0xE1 0x2B 0xD3 0x78 取固定值 2 總長 4個字節(包括包頭包尾的長度) 3 消息類型 0x21 或者 0x22 用於區別數據包的類型 4 XML流長度 XML格式數據的長度(4bytes) 5 XML格式數據 為所傳遞的XML報文 6 包尾 0xFF 0xFF 取固定值
數據包協議類型說明如下表: 消息號 說明 XML格式 0x21 表示客戶端向服務端發送數據 XMLInfoSed 0x22 表示服務端向客戶端發送數據 XMLInfoReq
定義好通信協議之後,Socket通信就需要遵循這個協議,服務端和客戶端都只接收該遵循該協議的報文和發送該格式的報文。
isListener = =[] arrMsg = [ * arrLen = (arrLen != (arrMsg[] == ) = Buffer.BlockCopy(arrMsg, , arrNew, , arrLen - msg = Encoding.GetEncoding(= ; (arrMsg[] == ) [] arrNew = [ arrNew[] = ] = ] = ] = arrNew[] = [] xmlArr = , xmlArr, msg = Encoding.GetEncoding( hexLength = String.Format( arrNew[] = Convert.ToByte(hexLength.Substring(, ), ] = Convert.ToByte(hexLength.Substring(, ), ] = Convert.ToByte(hexLength.Substring(, ), ] = Convert.ToByte(hexLength.Substring(, ), dataLen = arrNew.Length + xmlArr.Length + dataHexLen = String.Format( arrNew[] = Convert.ToByte(dataHexLen.Substring(, ), ] = Convert.ToByte(dataHexLen.Substring(, ), ] = Convert.ToByte(dataHexLen.Substring(, ), ] = Convert.ToByte(dataHexLen.Substring(, ), [] newArr = , newArr, - ] = - ] = Socket toclientSocket = == IPEndPoint(address, [] { }); [] { }); clientReqSocket.Close(); =
在這裡本服務成為一個類似中轉站的機器,客戶端向本服務發送數據,本服務接收數據,對數據進行解析,解析完成後將數據交給後台系統,後台系統對數據進行業務邏輯處理後,將結果數據發送給本服務,然後本服務將最後結果數據發送給客戶端。原本不需要本服務中間這一環節,客戶端和後台系統可以直接進行通信交互,但是因為業務要求,所以必須要有本服務這一中間環節。
對上面代碼進行說明:首頁本服務要先判斷接收到的數據為客戶端發送來的數據,還是後台系統需要向客戶端發送的數據。根據通信數據包結構定義,消息類型占1個字節,前面有包頭4字節和總長4字節共8個字節,所以消息類型在第9個字節的位置。對接收到的數據arrMsg[8]第9個字節進行判斷,如果arrMsg[8] = 0x22表示為客戶端發送來的數據,客戶端發送來的數據,本服務需要提取XML數據部分,然後對XML數據進行解析,將後台服務需要的數據發送給後台。
Buffer.BlockCopy(arrMsg, 13, arrNew, 0, arrLen - 15);去除頭13個字節和尾2個字節,提取XML數據部分。
如果arrMsg[8] == 0x22表示後台系統要向客戶端發送的數據,接收到後台系統發送過來的數據,首先要對數據進行封裝,將數據組裝成為約定好的XML結構(本服務接收到的數據就為XML數據),然後將該XML數據添加包頭包尾,重新封裝成為客戶端能夠識別的數據結構。將數據進行重新封裝後發送給客戶端,並且通知後台系統發送結果狀態。
在這裡主要是想跟大家分享,在網絡通信過程中,對於有通信接口格式定義的該如何進行交互。