我們選用的流是DataOutputStream和DataInputStream,下次再詳解java中的各種流的區別。
1.我們先創建對象:
1 private DataOutputStream outputStream = null; 2 private DataInputStream inputStream = null;
2.然后可在構造方法中使用傳入的socket對剛創建的對象定義:
1 public ClientHandleThread(Socket socket) { 2 this.socket = socket; 3 this.initTimer(); 4 try { 5 // socket.setSoTimeout(10000); 6 // writer = new BufferedWriter(new OutputStreamWriter( 7 // this.socket.getOutputStream(), "UTF-8")); 8 // reader = new BufferedReader(new InputStreamReader( 9 // this.socket.getInputStream(), "UTF-8")); 10 11 outputStream = new DataOutputStream(this.socket.getOutputStream()); 12 inputStream = new DataInputStream(this.socket.getInputStream()); 13 14 15 } catch (Exception e) { 16 e.printStackTrace(); 17 LogUtil.ERROR(e.getMessage()); 18 } 19 }
3.發送方法定義:
簡單的分片格式為:
定義一個byte數組 byte[] buffer = new byte[1024];
該數據中第一個byte作為分片定義格式存儲:
/** * 00000000 * 最高位代表是否是第一個分片,為‘1’代表是第一個分片 * 次高位代表是否是最后一個分片,為‘1’代表為最后一個分片 */ buffer[0] |= 0X80;//表示是第一個分片
buffer[0] |= 0X40;//表示是最后一個分片
當然,還可以依據需要加上具體的定義,可以參考網絡協議的報頭進行設計,有需要可以查看《計算機網絡》一書。
該方法分為三種走向:
當數據byte數組bytes的大小-> 0<bytes.length<=1023 時:不用分片,直接定義該片為最后一片buffer[0] |= 0X40;//表示是最后一個分片,直接發送
當數據byte數組bytes的大小-> 1023<bytes.length<=2046時,需要分為兩片
當數據byte數組bytes的大小-> 2046<bytes.length時,首先要切出首片(1023大小),然后依據while(remainSize>bufferSize)循環切出中間片,最后剩下的數據量大小<=1023,這作為最后一個分片。
具體的可以參考下列代碼:
1 // 發送 2 public void send(String data) { 3 try { 4 //需要設置"UTF-8"編碼,避免中文造成的亂碼 5 byte[] bytes = (data + "\r\n").getBytes("UTF-8"); 6 int posotion = 0; 7 int remainSize = bytes.length;//剩余數據量大小 8 int bufferSize = 1023;//緩沖區數據量大小+1 9 if(remainSize > bufferSize) 10 { 11 remainSize -=bufferSize; 12 byte[] buffer = new byte[1024]; 13 buffer[0] = 0;//初始化 14 /** 15 * 00000000 16 * 最高位代表是否是第一個分片,為‘1’代表是第一個分片 17 * 次高位代表是否是最后一個分片,為‘1’代表為最后一個分片 18 */ 19 buffer[0] |= 0X80;//表示是第一個分片 20 System.arraycopy(bytes, posotion, buffer, 1, bufferSize); 21 posotion += bufferSize; 22 this.outputStream.write(buffer); 23 this.outputStream.flush(); 24 25 } 26 while (remainSize>bufferSize) { 27 remainSize -= bufferSize; 28 byte[] buffer = new byte[1024]; 29 buffer[0] = 0;//初始化 30 // buffer[0] |= 0X80;//表示是第一個分片 31 // buffer[0] |= 0X40;//表示是最后一個分片 32 System.arraycopy(bytes, posotion, buffer, 1, bufferSize); 33 posotion += bufferSize; 34 this.outputStream.write(buffer); 35 this.outputStream.flush(); 36 37 } 38 if(remainSize > 0) 39 { 40 byte[] buffer = new byte[remainSize+1]; 41 buffer[0] = 0;//初始化 42 // buffer[0] |= 0X80;//表示是第一個分片 43 buffer[0] |= 0X40;//表示是最后一個分片 44 System.arraycopy(bytes, posotion, buffer, 1, remainSize); 45 this.outputStream.write(buffer); 46 this.outputStream.flush(); 47 } 48 49 // this.writer.write(data + "\r\n"); 50 // this.writer.flush(); 51 System.out.println("發送"+data); 52 } catch (IOException e) { 53 LogUtil.ERROR(e.getMessage()); 54 e.printStackTrace(); 55 } 56 57 }
4.下面是接收處理代碼:
需要表達的一點是,socket會依據切片的順序發送,一般不會造成切片的順序顛倒,當然嚴謹一些更好,最好增加數據包的序列號和編號。
下面只是一個簡單示例:
1 try { 2 // System.out.println(RunFlag); 3 4 //char chars[] = new char[1024]; 5 byte bytes[] = new byte[1024]; 6 int len = 0; 7 StringBuilder jsonBuffer = new StringBuilder(); 8 String temp = null; 9 int index = 0; 10 // while ((len = reader.read(chars)) != -1) { 11 // temp = new String(chars, 0, len); 12 // if ((index = temp.indexOf("\n")) != -1) {// 遇到\n時就結束接收 13 // jsonBuffer.append(temp.substring(0, index)); 14 // break; 15 // } 16 // jsonBuffer.append(temp); 17 // } 18 19 20 while ((len = inputStream.read(bytes)) != -1) { 21 temp = new String(bytes, 1, len-1,"UTF-8"); 22 if ((index = temp.indexOf("\n")) != -1 && (bytes[0] &= 0X40)==0X40) {// 遇到\n時就結束接收和最后一個分片 23 jsonBuffer.append(temp.substring(0, index)); 24 break; 25 } 26 jsonBuffer.append(temp); 27 } 28 29 30 String jsonString = jsonBuffer.toString(); 31
......
32 } catch (Exception e) { 33 LogUtil.ERROR(e.toString()); 34 }
這里只是簡單的判斷一下是否為最后一個分片,可以在此基礎上加上更嚴謹的判斷。
謝謝您的閱讀,希望對您有些幫助。