1. 程式人生 > >java socket報文通訊(二)報文的封裝

java socket報文通訊(二)報文的封裝

昨天我們談了怎麼建立socket通訊的服務端和客戶端,今天我們就來談一談怎麼封裝報文。

什麼是報文這裡我就不在闡述了,不清楚的朋友可以自己去查資料。我們今天要談的報文主要友以下幾個部分組成:

3位同步校驗位+8位報文長度+報文頭+報文體+32位MD5校驗位

基本格式如下:

0X110X120X1300000232<?xml version="1.0" encoding="GBK"?><ROOT><Code>0204</Code><Date>20141223</Date><No>141223010008152</No><Code>17010001</Code><Name>張三</Name></ROOT>B251AB76B11114DB176023A0AA27A524

說明:

  前面的0X110X120X13是3位16進位制的同部位,這裡為了大家理解,所以就以字元的形式謝出來了。00000232是報文長度。<?xml version="1.0" encoding="GBK"?><ROOT><Code>0204</Code><Date>20141223</Date><No>141223010008152</No><Code>17010001</Code></ROOT>是報文頭。即每個報文都包含的資訊。<Name>張三</Name>是報文體。B251AB76B11114DB176023A0AA27A524是加密資料。

關於如何將物件轉換為xml格式的報文我將在下一篇寫,這裡主要是給大家如何將如上的這些字串轉化為位元組以及如何傳送和接收報文。

1.建立報文的物件

  1. publicclass SocketPacket {  
  2.     private String bodyLen;  
  3.     private String body;  
  4.     private String syncStr;  
  5.     private String md5;  
  6.     public String getBodyLen() {  
  7.         return bodyLen;  
  8.     }  
  9.     public
     String getBody() {  
  10.         return body;  
  11.     }  
  12.     public String getSyncStr() {  
  13.         return syncStr;  
  14.     }  
  15.     public String getMd5() {  
  16.         return md5;  
  17.     }  
  18.     publicvoid setBodyLen(String bodyLen) {  
  19.         this.bodyLen = bodyLen;  
  20.     }  
  21.     publicvoid setBody(String body) {  
  22.         this.body = body;  
  23.     }  
  24.     publicvoid setSyncStr(String syncStr) {  
  25.         this.syncStr = syncStr;  
  26.     }  
  27.     publicvoid setMd5(String md5) {  
  28.         this.md5 = md5;  
  29.     }  
  30.     publicbyte[] getByteStream() throws UnsupportedEncodingException{  
  31.         byte[] bodyBytes = this.body.getBytes("gbk");//獲得body的位元組陣列
  32.         int bodyLength = bodyBytes.length;  
  33.         int socketLength = 3+bodyLength+8+32;  
  34.         byte [] soc = newbyte[socketLength];  
  35.         //新增校驗資料
  36.         int index = 0;  
  37.         soc[0]=0x11;  
  38.         soc[1]=0x12;  
  39.         soc[2]=0x13;  
  40.         index+=3;  
  41.         //新增8位報文長度(我的博文中也有NumberFormat的用法介紹)
  42.         NumberFormat numberFormat = NumberFormat.getNumberInstance();  
  43.         numberFormat.setMinimumIntegerDigits(8);  
  44.         numberFormat.setGroupingUsed(false);  
  45.         byte [] num = numberFormat.format(socketLength).getBytes();  
  46.         for(int i = 0;i<8;i++){  
  47.             soc[index++]= num[i];  
  48.         }  
  49.         //新增body內容
  50.         for(int i = 0;i<bodyLength;i++){  
  51.             soc[index++] = bodyBytes[i];  
  52.         }  
  53.         //新增md5校驗碼
  54.         byte [] md5Bytes = this.md5.getBytes();  
  55.         for (int i = 0; i < num.length; i++) {  
  56.             soc[index++] = md5Bytes[i];  
  57.         }  
  58.         return soc;  
  59.     }  
  60.     //位元組裝轉報文string
  61.     public String getString(byte [] socketBytes){  
  62.         String syncStr = this.bytesToString(socketBytes, 03);  
  63.         String socketLength = this.bytesToString(socketBytes, 33+8);  
  64.         String body = this.bytesToString(socketBytes, 3+8, socketBytes.length-32);  
  65.         String md5 = this.bytesToString(socketBytes,socketBytes.length-32,socketBytes.length);  
  66.         return syncStr+socketLength+body+md5;  
  67.     }  
  68.     //將位元組陣列轉化為string
  69.     public String bytesToString(byte [] bytes,int start,int end){  
  70.         String str = "";  
  71.         if(bytes.length<end-start){  
  72.             return str;  
  73.         }  
  74.         byte [] bs = newbyte[end-start];  
  75.         for(int i = 0;i<end-start;i++){  
  76.             bs[i] = bytes[start++];  
  77.         }  
  78.         str = new String(bs);  
  79.         return str;  
  80.     }  
  81.     public String toString(){  
  82.         returnthis.syncStr+this.bodyLen+this.body+this.md5;  
  83.     }  
  84. }  

2.封裝傳送和接收報文的工具類
  1. /** 
  2.  * 報文傳送 
  3.  */
  4. publicclass SockeUtil {  
  5.     Socket socket = null;  
  6.     public SockeUtil(String ip,int port) throws UnknownHostException, IOException{  
  7.         socket = new Socket(ip, port);  
  8.     }  
  9.     //
  10.     public SocketPacket sentSocket(SocketPacket socketPacket) throws UnsupportedEncodingException, IOException{  
  11.         SocketPacket sPacket = new SocketPacket();  
  12.         OutputStream output=null;  
  13.         InputStream input =null;  
  14.         // 同步字串(3byte)
  15.         byte[] sync = null//
  16.         byte[] bodyLen = null// 8位長度
  17.         byte[] body = null// 內容
  18.         byte[] md5 = null;  // MD5
  19.         output = socket.getOutputStream();  
  20.         //寫資料傳送報文
  21.         output.write(socketPacket.getByteStream());  
  22.         //獲得服務端返回的資料
  23.         input = socket.getInputStream();  
  24.         sync = this.streamToBytes(input,3);  
  25.         bodyLen = this.streamToBytes(input, 8);  
  26.         String lenString = new String(bodyLen);  
  27.         int len = Integer.valueOf(lenString);  
  28.         body = this.streamToBytes(input, len);  
  29.         md5 = this.streamToBytes(input, 32);  
  30.         sPacket.setSyncStr(new String(sync,Charset.forName("gbk")));  
  31.         socketPacket.setBodyLen(new String(bodyLen,Charset.forName("gbk")));  
  32.         socketPacket.setBody(new String(body,Charset.forName("gbk")));  
  33.         socketPacket.setMd5(new String(md5,Charset.forName("gbk")));  
  34.         return sPacket;  
  35.     }  
  36.     publicbyte[] streamToBytes(InputStream inputStream,int len){  
  37.         /** 
  38.          * inputStream.read(要複製到得位元組陣列,起始位置下標,要複製的長度) 
  39.          * 該方法讀取後input的下標會自動的後移,下次讀取的時候還是從上次讀取後移動到的下標開始讀取 
  40.          * 所以每次讀取後就不需要在制定起始的下標了 
  41. 相關推薦

    java socket報文通訊報文封裝

    昨天我們談了怎麼建立socket通訊的服務端和客戶端,今天我們就來談一談怎麼封裝報文。 什麼是報文這裡我就不在闡述了,不清楚的朋友可以自己去查資料。我們今天要談的報文主要友以下幾個部分組成: 3位同步校驗位+8位報文長度+報文頭+報文體+32位MD5校驗位 基本格式

    Python Socket網路程式設計區域網內和區域網與廣域網的持續通訊

    目錄 前言 IP地址 簡介 公有IP 私有IP 區域網之間網路通訊 前提 功能描述

    unity3D中使用Socket進行資料通訊

    上一篇部落格主要介紹了使用socket搭建服務端和客戶端程式,這一篇來說說socket的資料傳輸,我們使用socket的目的是解決點對點之間的資料傳輸,之前提到了socket中一個重要的概念:埠。而socket傳輸資料的方式就是埠與埠之間以流(stream)的方式傳輸資料,s

    簡單的通訊----使用Socket實現TCP協議

    客戶端向伺服器端傳送訊息,伺服器端給客戶端反饋訊息。程式碼和上一篇的程式碼差不多。 Client端程式碼 package com.demo; import java.io.IOException; import java.io.InputStream; import java.io.OutputStre

    Java多執行緒 —— 執行緒安全、執行緒同步、執行緒間通訊含面試題集

    上一篇博文:Java多執行緒(一) —— 執行緒的狀態詳解中詳細介紹了執行緒的五種狀態及狀態間的轉換。本文著重介紹了執行緒安全的相關知識點,包括執行緒同步和鎖機制、執行緒間通訊以及相關面試題的總結 一、執行緒安全 多個執行緒在執行同一段程式碼的時候,每次的執行結果和單執行緒執行的結果都是一樣的,不存在執行結果

    JAVA併發程式設計——執行緒協作通訊

    執行緒間的協作 在前面我們瞭解了很多關於同步(互斥鎖)的問題,下面來看一下執行緒之間的協作。這裡主要說一下Java執行緒中的join()、sleep()、yield()、wait()、notify()和notifyAll()方法。其中wait()、notify(

    Java內存模型——重排序

    序列 依賴性 種類 如果 禁止 加載 runtime 屬於 style 一、重排序   重排序是指為了提高程序的執行效率,編譯器和處理器常常會對語句的執行順序或者指令的執行順序進行重排。 編譯器優化的重排序:編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執行順序

    java高級工程師

    代理 man 順序 方法 one java web 功能 acm dispatch 一、Java底層基礎題 1、SpringMVC的原理以及返回數據如何渲染到jsp/html上? 答:Spring MVC的核心就是 DispatcherServlet , 一個請求經過 Di

    JAVA基礎實例

    for bin 存在 void hset search demo 個數字 .so 1.做一個飼養員給動物餵食物的樣例體現JAVA中的面向對象思想,接口(抽象類)的用處 package com.softeem.demo; /** [email p

    Java多線程 —— 線程安全、線程同步、線程間通信含面試題集

    err 線程等待 共同點 -c java多線 能夠 空間 而不是 不一致 一、線程安全 多個線程在執行同一段代碼的時候,每次的執行結果和單線程執行的結果都是一樣的,不存在執行結果的二義性,就可以稱作是線程安全的。 講到線程安全問題,其實是指多線程環境下對共享資源的訪問可能會

    Java之集合初探Iterator叠代器,collections,打包/解包裝箱拆箱,泛型(Generic),comparable接口

    基本 generate 等於 框架 ring bin list() each 是否 Iterator(叠代器) 所有實現了Collection接口的容器都有一個iterator方法, 用來返回一個實現了Iterator接口的對象 Iterator對象稱作叠代器, 用來

    Java總結篇系列:Java多線程

    文章 睡眠 blog setdeamon java多線程 cep public pan level Java總結篇系列:Java多線程(二) 本文承接上一篇文章《Java總結篇系列:Java多線程(一)》。 四.Java多線程的阻塞狀態與線程控制 上文已經提到Jav

    Java學習之路流程控制語句

    循環 cas 學習之路 將不 乘法表 length 跳出循環 spa int if、if…else…語句 if (true) { System.out.println("為真時執行");

    Java基礎—IO小結大綱待更新

    16px 文件復制 buffere tro 順序 -a [] 啟用 -c 一、緩沖流的使用   每個字節流都有對應的緩沖流:      BufferedInputStream / BufferedOutputStream   構造器:         方法摘要

    JAVA基礎-IO流

    直寫 eno 接口 寫入 print lis ted his ride 一、字節流 字節流是通過字節來進行讀寫操作的,他的使用對象相比於字符流來說更加的廣泛。這主要是因為他們讀寫文件的方式而決定的。字符流讀寫文件時是將讀取到的字節通過默認編碼表轉換成字符,在通

    Java多線程

    set static 生命 斷線 true 參考 clas 方法 test 1.多線程的阻塞狀態   join():一個線程調用了join()方法,必須等待另一個線程執行完畢後才能執行 package jsontest; public class RunableDem

    java版雲筆記

    blank app mar emc mt4 雲筆記 shu cmm ndt qC50f曬06渙hx厙咆2http://www.docin.com/nwghs11486 評z謁64a癡嘶06棵自暮0http://jz.docin.com/zdng396 5crl71也

    Java date相關 格式化

    天數 所在 fda 最後一天 ria int () ktr private import java.util.Calendar; import java.util.Date;import java.util.GregorianCalendar; public class Z

    Java框架之Struts2

    war cit post extend bst edi 關系 執行 erp 一、Action 配置說明 //請求的直接轉發 <package name="packageUser" namespace="" extends="struts-default">

    Java線程總結

    @override end system interrupt clas this trace trac inf 自定義線程的數據可以共享,也可以不共享,這要看具體的實現方式。 1.不共享數據多線程實現方式: public class MyThread extends T