java Socket 使用通用json包 傳送 json物件
阿新 • • 發佈:2019-01-02
在使用json進行socket進行通訊中,由於伺服器使用的json 和 客戶端使用的json版本不同,因此改用通用的json包來通訊。
可以通用,而且不必使用其他的一些需要引入的其他json依賴包
文章中的例子是將一張圖片傳送到伺服器端,伺服器端收到資訊之後返回給客戶端是否接受成功的資訊
這裡貼出客戶端與伺服器端的程式碼
客戶端:
- package service;
- import java.io.ByteArrayOutputStream;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import
- import java.net.Socket;
- import java.util.HashMap;
- import java.util.Map;
- import org.json.JSONArray;
- import org.json.JSONException;
- import org.json.JSONObject;
- import java.io.BufferedInputStream;
- import cn.edu.thu.cv.util.Base64Image;
- publicclass Client {
- publicstatic
- publicstaticfinalint PORT = 12345;//伺服器埠號
- publicstaticint register(String name,String imgPath,int opNum){
- String imgStr = Base64Image.GetImageStr(imgPath);//是將圖片的資訊轉化為base64編碼
- int isRegSuccess = 0;
- while (true) {
- Socket socket = null;
- try {
- //建立一個流套接字並將其連線到指定主機上的指定埠號
- socket = new Socket(IP_ADDR, PORT);
- System.out.println("連線已經建立");
- //向伺服器端傳送資料
- Map<String, String> map = new HashMap<String, String>();
- map.put("name",name);
- map.put("img",imgStr);
- map.put("op",opNum+"");
- //將json轉化為String型別
- JSONObject json = new JSONObject(map);
- String jsonString = "";
- jsonString = json.toString();
- //將String轉化為byte[]
- //byte[] jsonByte = new byte[jsonString.length()+1];
- byte[] jsonByte = jsonString.getBytes();
- DataOutputStream outputStream = null;
- outputStream = new DataOutputStream(socket.getOutputStream());
- System.out.println("發的資料長度為:"+jsonByte.length);
- outputStream.write(jsonByte);
- outputStream.flush();
- System.out.println("傳輸資料完畢");
- socket.shutdownOutput();
- //讀取伺服器端資料
- DataInputStream inputStream = null;
- String strInputstream ="";
- inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
- strInputstream=inputStream.readUTF();
- System.out.println("輸入資訊為:"+strInputstream);
- JSONObject js = new JSONObject(strInputstream);
- System.out.println(js.get("isSuccess"));
- isRegSuccess=Integer.parseInt((String) js.get("isSuccess"));
- // 如接收到 "OK" 則斷開連線
- if (js != null) {
- System.out.println("客戶端將關閉連線");
- Thread.sleep(500);
- break;
- }
- } catch (Exception e) {
- System.out.println("客戶端異常:" + e.getMessage());
- break;
- } finally {
- if (socket != null) {
- try {
- socket.close();
- } catch (IOException e) {
- socket = null;
- System.out.println("客戶端 finally 異常:" + e.getMessage());
- }
- }
- }
- }
- return isRegSuccess;
- }
- publicstaticvoid main(String[] args) {
- register("gongyunfei","D:/test1.jpg",1);//第三個引數為操作型別 伺服器能夠知道你在進行什麼操作
- }
- }
伺服器端的程式碼:
- package service;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Date;
- import java.text.SimpleDateFormat;
- import java.io.BufferedOutputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import org.json.JSONArray;
- import org.json.JSONException;
- import org.json.JSONObject;
- import cn.edu.thu.cv.util.Base64Image;
- publicclass Server {
- publicstaticfinalint PORT = 12345;//監聽的埠號
- publicstaticvoid main(String[] args) {
- System.out.println("伺服器啟動...\n");
- // System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
- Server server = new Server();
- server.init();
- }
- publicvoid init() {
- try {
- ServerSocket serverSocket = new ServerSocket(PORT);
- while (true) {
- // 一旦有堵塞, 則表示伺服器與客戶端獲得了連線
- Socket client = serverSocket.accept();
- // 處理這次連線
- new HandlerThread(client);
- }
- } catch (Exception e) {
- System.out.println("伺服器異常: " + e.getMessage());
- }
- }
- privateclass HandlerThread implements Runnable {
- private Socket socket;
- public HandlerThread(Socket client) {
- socket = client;
- new Thread(this).start();
- }
- publicvoid run() {
- try {
- // 讀取客戶端資料
- System.out.println("客戶端資料已經連線");
- DataInputStream inputStream = null;
- DataOutputStream outputStream = null;
- String strInputstream ="";
- inputStream =new DataInputStream(socket.getInputStream());
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] by = newbyte[2048];
- int n;
- while((n=inputStream.read(by))!=-1){
- baos.write(by,0,n);
- }
- strInputstream = new String(baos.toByteArray());
- // System.out.println("接受到的資料長度為:"+strInputstream);
- socket.shutdownInput();
- // inputStream.close();
- baos.close();
- // 處理客戶端資料
- //將socket接受到的資料還原為JSONObject
- JSONObject json = new JSONObject(strInputstream);
- int op =Integer.parseInt((String)json.get("op"));
- System.out.println(op);
- switch(op){
- //op為1 表示收到的客戶端的資料為註冊資訊 op為2表示收到客戶端的資料為檢索資訊
- //當用戶進行的操作是註冊時
- case1: String imgStr = json.getString("img");
- String name = json.getString("name");
- //isSuccess 表示是否註冊成功
- String isSuccess="1";
- // System.out.println("imgStr:"+imgStr);
- //用系統時間作為生成圖片的名字 格式為yyyy-MM-dd-HH-mm-ss
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
- String imgName = df.format(new Date());
- Base64Image.GenerateImage(imgStr,"D:\\fromjia\\imageDB\\primary\\"+imgName+".jpg");
- //do something to process this image
- //if success, return set isSuccess "1"
- //else set "0"
- System.out.println(name);
- System.out.println("伺服器接受資料完畢");
- // 向客戶端回覆資訊 --json物件//to be continued;
- Map<String, String> map = new HashMap<String, String>();
- map.put("isSuccess", isSuccess);
- json = new JSONObject(map);
- String jsonString = json.toString();
- outputStream = new DataOutputStream(new BufferedOutputStream (socket.getOutputStream()));
- outputStream.writeUTF(jsonString);
- outputStream.flush();
- outputStream.close();
- System.out.println("註冊完成");
- break;
- }
- outputStream.close();
- } catch (Exception e) {
- System.out.println("伺服器 run 異常: " + e.getMessage());
- } finally {
- if (socket != null) {
- try {
- socket.close();
- } catch (Exception e) {
- socket = null;
- System.out.println("服務端 finally 異常:" + e.getMessage());
- }
- }
- }
- }
- }
- }
文中所要引用的import cn.edu.thu.cv.util.Base64Image程式碼為:
- package cn.edu.thu.cv.util;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import sun.misc.BASE64Decoder;
- import sun.misc.BASE64Encoder;
- publicclass Base64Image
- {
- publicstatic String GetImageStr(String imapath)
- {//將圖片檔案轉化為位元組陣列字串,並對其進行Base64編碼處理
- InputStream in = null;
- byte[] data = null;
- //讀取圖片位元組陣列
- try
- {
- in = new FileInputStream(imapath);
- data = newbyte[in.available()];
- in.read(data);
- in.close();
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- //對位元組陣列Base64編碼
- BASE64Encoder encoder = new BASE64Encoder();
- return encoder.encode(data);//返回Base64編碼過的位元組陣列字串
- }
- publicstaticboolean GenerateImage(String imgStr, String output)
- {//對位元組陣列字串進行Base64解碼並生成圖片
- if (imgStr == null) //影象資料為空
- returnfalse;
- BASE64Decoder decoder = new BASE64Decoder();
- try
- {
- //Base64解碼
- byte[] b = decoder.decodeBuffer(imgStr);
- for(int i=0;i<b.length;++i)
- {
- if(b[i]<0)
- {//調整異常資料
- b[i]+=256;
- }
- }
- //生成jpeg圖片
- OutputStream out = new FileOutputStream(output);
- out.write(b);
- out.flush();
- out.close();
- returntrue;
- }
- catch (Exception e)
- {
- returnfalse;
- }
- }
- }
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();