java Socket 使用通用json包 发送 json对象
在使用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 = "***.***.***.***";//服务器地址 这里要改成服务器的ip
- public 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();