1. 程式人生 > >java Socket 使用通用json包 傳送 json物件

java Socket 使用通用json包 傳送 json物件

在使用json進行socket進行通訊中,由於伺服器使用的json 和 客戶端使用的json版本不同,因此改用通用的json包來通訊。

可以通用,而且不必使用其他的一些需要引入的其他json依賴包

文章中的例子是將一張圖片傳送到伺服器端,伺服器端收到資訊之後返回給客戶端是否接受成功的資訊

這裡貼出客戶端與伺服器端的程式碼

客戶端:

  1. package service;  
  2. import java.io.ByteArrayOutputStream;  
  3. import java.io.DataInputStream;  
  4. import java.io.DataOutputStream;  
  5. import
     java.io.IOException;  
  6. import java.net.Socket;  
  7. import java.util.HashMap;  
  8. import java.util.Map;  
  9. import org.json.JSONArray;  
  10. import org.json.JSONException;  
  11. import org.json.JSONObject;  
  12. import java.io.BufferedInputStream;  
  13. import cn.edu.thu.cv.util.Base64Image;  
  14. publicclass Client {  
  15.     publicstatic
    final String IP_ADDR = "***.***.***.***";//伺服器地址  這裡要改成伺服器的ip
  16.     publicstaticfinalint PORT = 12345;//伺服器埠號  
  17.     publicstaticint register(String name,String imgPath,int opNum){  
  18.         String imgStr = Base64Image.GetImageStr(imgPath);//是將圖片的資訊轉化為base64編碼
  19.         int isRegSuccess = 0;  
  20.          while (true) {    
  21.                 Socket socket = null;  
  22.                 try {  
  23.                     //建立一個流套接字並將其連線到指定主機上的指定埠號
  24.                     socket = new Socket(IP_ADDR, PORT);    
  25.                     System.out.println("連線已經建立");          
  26.                     //向伺服器端傳送資料  
  27.                     Map<String, String> map = new HashMap<String, String>();  
  28.                     map.put("name",name);  
  29.                     map.put("img",imgStr);  
  30.                     map.put("op",opNum+"");  
  31.                     //將json轉化為String型別  
  32.                     JSONObject json = new JSONObject(map);  
  33.                     String jsonString = "";  
  34.                         jsonString = json.toString();  
  35.                     //將String轉化為byte[]
  36.                     //byte[] jsonByte = new byte[jsonString.length()+1];
  37.                     byte[] jsonByte = jsonString.getBytes();  
  38.                     DataOutputStream outputStream = null;  
  39.                     outputStream = new DataOutputStream(socket.getOutputStream());  
  40.                         System.out.println("發的資料長度為:"+jsonByte.length);  
  41.                     outputStream.write(jsonByte);  
  42.                     outputStream.flush();  
  43.                         System.out.println("傳輸資料完畢");  
  44.                         socket.shutdownOutput();  
  45.                     //讀取伺服器端資料  
  46.                     DataInputStream inputStream = null;  
  47.                     String strInputstream ="";  
  48.                     inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));   
  49.                     strInputstream=inputStream.readUTF();  
  50.                     System.out.println("輸入資訊為:"+strInputstream);  
  51.                     JSONObject js = new JSONObject(strInputstream);  
  52.                     System.out.println(js.get("isSuccess"));  
  53.                     isRegSuccess=Integer.parseInt((String) js.get("isSuccess"));   
  54.                     // 如接收到 "OK" 則斷開連線  
  55.                     if (js != null) {    
  56.                         System.out.println("客戶端將關閉連線");    
  57.                         Thread.sleep(500);    
  58.                         break;    
  59.                     }    
  60.                 } catch (Exception e) {  
  61.                     System.out.println("客戶端異常:" + e.getMessage());   
  62.                     break;  
  63.                 } finally {  
  64.                     if (socket != null) {  
  65.                         try {  
  66.                             socket.close();  
  67.                         } catch (IOException e) {  
  68.                             socket = null;   
  69.                             System.out.println("客戶端 finally 異常:" + e.getMessage());   
  70.                         }  
  71.                     }  
  72.                 }  
  73.             }  
  74.          return isRegSuccess;     
  75.     }  
  76.     publicstaticvoid main(String[] args) {    
  77.           register("gongyunfei","D:/test1.jpg",1);//第三個引數為操作型別 伺服器能夠知道你在進行什麼操作
  78.    }    
  79. }   

伺服器端的程式碼:

  1. package service;  
  2. import java.net.ServerSocket;  
  3. import java.net.Socket;  
  4. import java.util.ArrayList;  
  5. import java.util.HashMap;  
  6. import java.util.Map;  
  7. import java.util.Date;  
  8. import java.text.SimpleDateFormat;  
  9. import java.io.BufferedOutputStream;  
  10. import java.io.ByteArrayOutputStream;  
  11. import java.io.DataInputStream;  
  12. import java.io.DataOutputStream;  
  13. import org.json.JSONArray;  
  14. import org.json.JSONException;  
  15. import org.json.JSONObject;  
  16. import cn.edu.thu.cv.util.Base64Image;  
  17. publicclass Server {  
  18.     publicstaticfinalint PORT = 12345;//監聽的埠號   
  19.     publicstaticvoid main(String[] args) {    
  20.         System.out.println("伺服器啟動...\n");    
  21.       //  System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
  22.         Server server = new Server();    
  23.         server.init();    
  24.     }    
  25.     publicvoid init() {    
  26.         try {    
  27.             ServerSocket serverSocket = new ServerSocket(PORT);    
  28.             while (true) {    
  29.                 // 一旦有堵塞, 則表示伺服器與客戶端獲得了連線  
  30.                 Socket client = serverSocket.accept();    
  31.                 // 處理這次連線  
  32.                 new HandlerThread(client);    
  33.             }    
  34.         } catch (Exception e) {    
  35.             System.out.println("伺服器異常: " + e.getMessage());    
  36.         }    
  37.     }    
  38.     privateclass HandlerThread implements Runnable {    
  39.         private Socket socket;    
  40.         public HandlerThread(Socket client) {    
  41.             socket = client;    
  42.             new Thread(this).start();    
  43.         }    
  44.         publicvoid run() {    
  45.             try {    
  46.                 // 讀取客戶端資料  
  47.                 System.out.println("客戶端資料已經連線");  
  48.                 DataInputStream inputStream = null;  
  49.                 DataOutputStream outputStream = null;  
  50.                 String strInputstream ="";           
  51.                 inputStream =new DataInputStream(socket.getInputStream());                   
  52.                 ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  53.                 byte[] by = newbyte[2048];  
  54.                 int n;  
  55.                 while((n=inputStream.read(by))!=-1){  
  56.                     baos.write(by,0,n);           
  57.                 }  
  58.                 strInputstream = new String(baos.toByteArray());  
  59. //                System.out.println("接受到的資料長度為:"+strInputstream);
  60.                 socket.shutdownInput();  
  61. //                inputStream.close();
  62.                 baos.close();  
  63.                 // 處理客戶端資料  
  64.                 //將socket接受到的資料還原為JSONObject
  65.                 JSONObject json = new JSONObject(strInputstream);         
  66.                 int op =Integer.parseInt((String)json.get("op"));    
  67.                 System.out.println(op);  
  68.                 switch(op){  
  69.                 //op為1 表示收到的客戶端的資料為註冊資訊     op為2表示收到客戶端的資料為檢索資訊     
  70.                 //當用戶進行的操作是註冊時
  71.                 case1: String imgStr = json.getString("img");  
  72.                         String name   = json.getString("name");  
  73.                        //isSuccess 表示是否註冊成功
  74.                         String isSuccess="1";  
  75.                        // System.out.println("imgStr:"+imgStr);
  76.                         //用系統時間作為生成圖片的名字   格式為yyyy-MM-dd-HH-mm-ss
  77.                         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");  
  78.                         String imgName = df.format(new Date());  
  79.                         Base64Image.GenerateImage(imgStr,"D:\\fromjia\\imageDB\\primary\\"+imgName+".jpg");  
  80.                         //do something to process this image                      
  81.                         //if success, return set isSuccess "1"
  82.                         //else set "0"  
  83.                         System.out.println(name);                   
  84.                         System.out.println("伺服器接受資料完畢");  
  85.                         // 向客戶端回覆資訊  --json物件//to be continued;
  86.                         Map<String, String> map = new HashMap<String, String>();  
  87.                         map.put("isSuccess", isSuccess);  
  88.                         json = new JSONObject(map);  
  89.                     String jsonString = json.toString();                        
  90.                     outputStream = new DataOutputStream(new BufferedOutputStream (socket.getOutputStream()));     
  91.                     outputStream.writeUTF(jsonString);  
  92.                     outputStream.flush();  
  93.                     outputStream.close();  
  94.                     System.out.println("註冊完成");  
  95.                         break;                                                                                         
  96.                 }   
  97.                 outputStream.close();  
  98.             } catch (Exception e) {    
  99.                 System.out.println("伺服器 run 異常: " + e.getMessage());    
  100.             } finally {    
  101.                 if (socket != null) {    
  102.                     try {    
  103.                         socket.close();    
  104.                     } catch (Exception e) {    
  105.                         socket = null;    
  106.                         System.out.println("服務端 finally 異常:" + e.getMessage());    
  107.                     }    
  108.                 }    
  109.             }   
  110.         }    
  111.     }    
  112. }    

文中所要引用的import cn.edu.thu.cv.util.Base64Image程式碼為:

  1. package cn.edu.thu.cv.util;  
  2. import java.io.FileInputStream;  
  3. import java.io.FileOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.OutputStream;  
  7. import sun.misc.BASE64Decoder;  
  8. import sun.misc.BASE64Encoder;  
  9. publicclass Base64Image   
  10. {  
  11.     publicstatic String GetImageStr(String imapath)  
  12.     {//將圖片檔案轉化為位元組陣列字串,並對其進行Base64編碼處理
  13.         InputStream in = null;  
  14.         byte[] data = null;  
  15.         //讀取圖片位元組陣列
  16.         try
  17.         {  
  18.             in = new FileInputStream(imapath);          
  19.             data = newbyte[in.available()];  
  20.             in.read(data);  
  21.             in.close();  
  22.         }   
  23.         catch (IOException e)   
  24.         {  
  25.             e.printStackTrace();  
  26.         }  
  27.         //對位元組陣列Base64編碼
  28.         BASE64Encoder encoder = new BASE64Encoder();  
  29.         return encoder.encode(data);//返回Base64編碼過的位元組陣列字串
  30.     }  
  31.     publicstaticboolean GenerateImage(String imgStr, String output)  
  32.     {//對位元組陣列字串進行Base64解碼並生成圖片
  33.         if (imgStr == null//影象資料為空
  34.             returnfalse;  
  35.         BASE64Decoder decoder = new BASE64Decoder();  
  36.         try
  37.         {  
  38.             //Base64解碼
  39.             byte[] b = decoder.decodeBuffer(imgStr);  
  40.             for(int i=0;i<b.length;++i)  
  41.             {  
  42.                 if(b[i]<0)  
  43.                 {//調整異常資料
  44.                     b[i]+=256;  
  45.                 }  
  46.             }  
  47.             //生成jpeg圖片
  48.             OutputStream out = new FileOutputStream(output);      
  49.             out.write(b);  
  50.             out.flush();  
  51.             out.close();  
  52.             returntrue;  
  53.         }   
  54.         catch (Exception e)   
  55.         {  
  56.             returnfalse;  
  57.         }  
  58.     }  
  59. }  
之前認為寫的時候還是很簡單的,不過寫的過程中遇到了一些問題,將這些問題總結一下如下:

1.傳輸檔案過程中,要將檔案轉換成base64編碼。

2.要統一好程式設計的工具、配置環境,包括使用的具體包的形式,我這次遇到的情況是:甲寫伺服器端,使用的是json2.4的包,並且測試沒有問題。乙寫的客戶端引用了一個j2E,裡面包含了json2.1,而且json2.1無法刪除替換,這樣通訊方式就會改變,伺服器與客戶端無法完成通訊。只能使用通用json包,增加了不少工作量。

3.在使用org.json 中,傳輸比較小的字串,可以使用outputStream.writeUTF(String);這個函式來寫,但是當傳輸比較大的檔案的時候就必須將String轉化為byte[]來進行傳輸,不然會報出異常說是編碼太大無法傳輸。

4.在傳送完資料之後要記得flush();

5.在使用outputStream.close();或者inputStream.close();來關閉伺服器的輸入流和輸出流的過程中,socket也會同時關閉,如果想只關閉輸入流或者輸出流而不關閉socket就可以使用socket.shutdownInput();