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 map = new HashMap();
		        	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 map = new HashMap();
		                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

 
  
 
  

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

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

你可能感兴趣的:(socket通信)