java Socket 使用通用json包 发送 json对象

来源:互联网 发布:windows 每10秒ping 编辑:程序博客网 时间:2024/06/04 18:43

在使用json进行socket进行通信中,由于服务器使用的json 和 客户端使用的json版本不同,因此改用通用的json包来通信。

引入的包为 org.json,jar   

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


文章中的例子是将一张图片发送到服务器端,服务器端收到信息之后返回给客户端是否接受成功的信息


这里贴出客户端与服务器端的代码

客户端:

package service;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;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;public class Client {public static final String IP_ADDR = "***.***.***.***";//服务器地址  这里要改成服务器的ippublic static final int PORT = 12345;//服务器端口号  public static int 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;}    public static void 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;public class Server {public static final int PORT = 12345;//监听的端口号       public static void main(String[] args) {          System.out.println("服务器启动...\n");        //  System.loadLibrary(Core.NATIVE_LIBRARY_NAME);        Server server = new Server();          server.init();      }        public void init() {          try {              ServerSocket serverSocket = new ServerSocket(PORT);              while (true) {                  // 一旦有堵塞, 则表示服务器与客户端获得了连接                  Socket client = serverSocket.accept();                  // 处理这次连接                  new HandlerThread(client);              }          } catch (Exception e) {              System.out.println("服务器异常: " + e.getMessage());          }      }        private class HandlerThread implements Runnable {          private Socket socket;          public HandlerThread(Socket client) {              socket = client;              new Thread(this).start();          }            public void run() {                       try {                  // 读取客户端数据              System.out.println("客户端数据已经连接");            DataInputStream inputStream = null;            DataOutputStream outputStream = null;            String strInputstream ="";                     inputStream =new DataInputStream(socket.getInputStream());                             ByteArrayOutputStream baos = new ByteArrayOutputStream();                byte[] by = new byte[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表示收到客户端的数据为检索信息                                     //当用户进行的操作是注册时                case 1: 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;public class Base64Image {    public static String GetImageStr(String imapath)    {//将图片文件转化为字节数组字符串,并对其进行Base64编码处理        InputStream in = null;        byte[] data = null;        //读取图片字节数组        try         {            in = new FileInputStream(imapath);                    data = new byte[in.available()];            in.read(data);            in.close();        }         catch (IOException e)         {            e.printStackTrace();        }        //对字节数组Base64编码        BASE64Encoder encoder = new BASE64Encoder();        return encoder.encode(data);//返回Base64编码过的字节数组字符串    }    public static boolean GenerateImage(String imgStr, String output)    {//对字节数组字符串进行Base64解码并生成图片        if (imgStr == null) //图像数据为空            return false;        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();            return true;        }         catch (Exception e)         {            return false;        }    }}

之前认为写的时候还是很简单的,不过写的过程中遇到了一些问题,将这些问题总结一下如下:

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();

1 0