Java Socket 通信 (四)

来源:互联网 发布:淘宝手机版详情页尺寸 编辑:程序博客网 时间:2024/05/21 06:39

前言:经过前三次的学习,今天又深入了一步。组长说,你尝试下传byte数组,你会遇到坑的。前几次,为了方便,我读流和写流都是用的readUTF()和writeUTF().直接写的String类型。于是我尝试了一下,直接传byte数组。代码如下:

Server端:

package mysocket.versiontwo;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;/** * Created by demi on 16/10/12. */public class JsonServer {    public static void main(String args[]) {        ServerSocket ss = null;        Socket s = null;        Thread thread = null;        try {            ss = new ServerSocket(3320);            while (true) {                s = ss.accept();                System.out.println("Client :" + s.getInetAddress() + " : " + s.getPort() + " 已连接》》》》》》");                thread = new Thread(new ServerThread(s));                thread.start();            }        } catch (IOException e) {            e.printStackTrace();        }    }}

ServerThread.java

package mysocket.versiontwo;import org.json.JSONException;import org.json.JSONObject;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;/** * Created by demi on 16/10/14. */public class ServerThread implements Runnable {    private Socket s = null;    DataInputStream dis = null;    DataOutputStream dos = null;    public ServerThread(Socket s) {        this.s = s;    }    @Override    public void run() {        try {            dos = new DataOutputStream(s.getOutputStream());            dis = new DataInputStream(s.getInputStream());            while (true) {                byte[] bytes = new byte[1024];                dis.read(bytes);               String data= new String( bytes ,"UTF-8");                System.out.println(new String( bytes ,"UTF-8"));                if (null != data) {                    if (!data.contains("data")) {                        JSONObject jo = new JSONObject(data);                        int a = jo.getInt("numA");                        int b = jo.getInt("numB");                        dos.write(creatSumJson(a, b).getBytes("UTF-8"));//写入数据到客户端                        dos.flush();                    } else {                        JSONObject jo = new JSONObject(data);                        int a = jo.getInt("data");                        for (int i = 0; i < 100; i++) {                            a++;                            dos.write(createRandomJson(a).getBytes("UTF-8"));//写入数据到客户端                            dos.flush();                        }                    }                }            }        } catch (Exception e) {            e.printStackTrace();            try {                dis.close();                dos.close();                s.close();                System.out.print("链接已断开");            } catch (IOException e1) {                e1.printStackTrace();            }        }    }    /**     * 模拟现实项目中的接口,在做了自加运算后创建一个json。     */    public static String createRandomJson(int a) {        JSONObject s = new JSONObject();        try {            s.put("data", a);        } catch (JSONException e) {            e.printStackTrace();        }        return s.toString();    }    /**     * 模拟现实项目中的接口,获取客户端的两个加数,做完加法后返回给客户端。     */    //    public static String creatSumJson(int a, int b) {        JSONObject s = new JSONObject();        try {            s.put("sum", a + b);        } catch (JSONException e) {            e.printStackTrace();        }        return s.toString();    }}


Client端:

package mysocket.versiontwo;import org.json.JSONException;import org.json.JSONObject;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;import java.util.Random;/** * Created by demi on 16/10/12. */public class JsonClient {    public static void main(String args[]){        DataOutputStream dos =null;        Thread chat = null;        Socket socket = null;        DataInputStream dis =null;        try {            socket =new Socket("127.0.0.1",3320);            dos =new DataOutputStream(socket.getOutputStream());            dos.write(createRandomJson().getBytes("UTF-8")); //写入数据到服务器端            chat = new Thread(new ChatThread(socket));            chat.start();            socket.setKeepAlive(true);            int i = 0;            while(i<=100){                Thread.sleep(1000);                dos.write(creatSumJson().getBytes("UTF-8"));//写入数据到服务器端                i++;            }        } catch (IOException e) {            e.printStackTrace();            try {                dos.close();                socket.close();                chat.stop();                System.out.print("链接已断开");            } catch (IOException e1) {                e1.printStackTrace();            }        } catch (InterruptedException e) {            e.printStackTrace();        }    }    /**     * 模拟现实项目中的接口,创建一个20以内的随机数的json,发送到服务器,让服务器做++运算,加一次向客户端推送一次结果。     */    public static String createRandomJson(){        JSONObject s = new JSONObject();        try {            s.put("data", new Random().nextInt(20));        } catch (JSONException e) {            e.printStackTrace();        }        return s.toString() ;    }    /**     * 模拟现实项目中的接口,创建两个100以内的随机数的json,发送到服务器,让服务器做完加法后返回给客户端。     */    //    public static String creatSumJson(){        JSONObject s =new JSONObject();        try {            s.put("numA", new Random().nextInt(100));            s.put("numB", new Random().nextInt(100));        } catch (JSONException e) {            e.printStackTrace();        }        return s.toString() ;    }}

ChatThread.Java

package mysocket.versiontwo;import java.io.DataInputStream;import java.io.IOException;import java.net.Socket;/** * Created by demi on 16/10/13. */public class ChatThread implements Runnable {    private Socket s = null;    DataInputStream dis =null;    public ChatThread(Socket s){        this.s = s;    }    @Override    public void run() {        try {            dis =new DataInputStream(s.getInputStream());            while(true){                byte[] bytes = new byte[1024];                dis.read(bytes);                System.out.println(new String( bytes ,"UTF-8")); //打印来自服务器的数据            }        } catch (IOException e) {            e.printStackTrace();        }    }}

正高高兴兴的run并和组长说,没坑啊。结果程序一运行起来,坑就来了!请看截图

我发现客户端读数据的时候,读的长度是不确定的,有时候一次性读的多,有时候就读一个。所以这就需要一个分隔机制,来限制读的长度。那首先想到的就是,在读流之前告诉对方,我的流的byte数组的长度。这样就可以避免这个问题了。还有一个问题就是,之前我还能通过json字段来判断是哪个接口,现在咋判断呢?这就需要cmd(命令号了)。那就在传json前,先把cmd,byte数组的长度传过去,再传json。但听前辈们说还谣传一个标识符,来标记是哪一次请求,防止多次请求过后,返回回来的结果对应不上。这个值传到服务器,服务器也会把这个值再传回来,客户端判断这个值与传过去的值是否一致。来对应请求。修改后的代码如下:

ServerThread.java

package mysocket.versionfour;import org.json.JSONException;import org.json.JSONObject;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;/** * Created by demi on 16/10/14. */public class ServerThread extends Thread {    private Socket s = null;    DataInputStream dis = null;    DataOutputStream dos = null;    public ServerThread(Socket s) {        this.s = s;    }    @Override    public void run() {        try {            dos = new DataOutputStream(s.getOutputStream());            dis = new DataInputStream(s.getInputStream());            while (true) {                readFromClient();            }        } catch (Exception e) {            e.printStackTrace();            try {                dis.close();                dos.close();                s.close();                System.out.print("链接已断开");            } catch (IOException e1) {                e1.printStackTrace();            }        }    }    /**     * 模拟现实项目中的接口,在做了自加运算后创建一个json。     */    public static String createRandomJson(int a) {        JSONObject s = new JSONObject();        try {            s.put("data", a);        } catch (JSONException e) {            e.printStackTrace();        }        return s.toString();    }    /**     * 模拟现实项目中的接口,获取客户端的两个加数,做完加法后返回给客户端。     */    //    public static String creatSumJson(int a, int b) {        JSONObject s = new JSONObject();        try {            s.put("sum", a + b);        } catch (JSONException e) {            e.printStackTrace();        }        return s.toString();    }    public void write2Client(byte[] bytes,int tag) throws  Exception{        dos.writeInt(bytes.length);//传过去的byte数组的长度        dos.writeInt(tag);        dos.write(bytes);        dos.flush();    }    public void readFromClient(){        try {            int length=dis.readInt();            byte[] bytes = new byte[length];            int cmd = dis.readInt();            int tag = dis.readInt();            dis.read(bytes,0,length);            String data= new String( bytes ,"UTF-8");            System.out.println(tag + ":" +new String( bytes ,"UTF-8"));            JSONObject jo = new JSONObject(data);            switch (cmd){                case CMD.SUM :                    int a = jo.getInt("numA");                    int b = jo.getInt("numB");                    write2Client(creatSumJson(a, b).getBytes("UTF-8"),tag);                    break;                case CMD.RANDOMADD :                    int random = jo.getInt("data");                    for (int i = 0; i < 100; i++) {                        random++;                        write2Client(createRandomJson(random).getBytes("UTF-8"),tag);                    }                    break;            }        } catch (Exception e) {            e.printStackTrace();        }    }}
ClientReadTHread.java

package mysocket.versionfour;import java.io.DataInputStream;import java.io.IOException;import java.net.Socket;/** * Created by demi on 16/10/13. */public class ClientReadThread extends Thread {    private Socket s = null;    DataInputStream dis =null;    public ClientReadThread(Socket s){        this.s = s;    }    @Override    public void run() {        try {            dis =new DataInputStream(s.getInputStream());            while(true){                readFromServer();            }        } catch (Exception e) {            e.printStackTrace();            try {                dis.close();                s.close();            } catch (IOException e1) {                e1.printStackTrace();            }        }    }    public void readFromServer() throws Exception{        int length=dis.readInt();        byte[] bytes = new byte[length];        int tag =dis.readInt();        dis.read(bytes,0,length);        System.out.println(tag+":"+new String( bytes ,"UTF-8")); //打印来自服务器的数据    }}


ClientWriteThread.java

package mysocket.versionfour;import org.json.JSONException;import org.json.JSONObject;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;import java.util.Random;/** * Created by demi on 16/10/13. */public class ClientWriteThread extends Thread {    private static int tag;    private Socket s = null;    DataOutputStream dos =null;    public ClientWriteThread(Socket s){        this.s = s;    }    @Override    public void run() {        try {            dos = new DataOutputStream(s.getOutputStream());            byte[] bytes = createRandomJson().getBytes("UTF-8");            write2Server( bytes, CMD.RANDOMADD);            int i = 0;            while (i <= 100) {                Thread.sleep(1000);                byte[] sumBytes = creatSumJson().getBytes("UTF-8");                write2Server( sumBytes, CMD.SUM);                i++;            }        } catch (Exception e) {            e.printStackTrace();            try {                dos.close();                s.close();            } catch (IOException e1) {                e1.printStackTrace();            }        }    }    /**     * 模拟现实项目中的接口,创建一个20以内的随机数的json,发送到服务器,让服务器做++运算,加一次向客户端推送一次结果。     */    public static String createRandomJson() {        JSONObject s = new JSONObject();        try {            s.put("data", new Random().nextInt(20));            tag = new Random().nextInt(1000)+1000;        } catch (JSONException e) {            e.printStackTrace();        }        return s.toString();    }    /**     * 模拟现实项目中的接口,创建两个100以内的随机数的json,发送到服务器,让服务器做完加法后返回给客户端。     */    public static String creatSumJson() {        JSONObject s = new JSONObject();        try {            s.put("numA", new Random().nextInt(100));            s.put("numB", new Random().nextInt(100));            tag = new Random().nextInt(1000)+1000;        } catch (JSONException e) {            e.printStackTrace();        }        return s.toString();    }    public void write2Server( byte[] bytes, int cmd) throws Exception {        dos.writeInt(bytes.length);//传过去的byte数组的长度        dos.writeInt(cmd);//命令号,通过命令号来辨别是哪个接口!        dos.writeInt(tag);//标志位,标记是那哪一次请求。        dos.write(bytes);        //dos.writeUTF(createRandomJson());        dos.flush();    }}

CMD.java

package mysocket.versionfour;/** * Created by demi on 16/10/14. */public class CMD {    //两加数求和    public static final int SUM = 1001;    //随机数自加一    public static final int RANDOMADD = 1002;}

运行结果就正常了。


这就是进步!下一步就开始封装Socket了!期待吧!


1 0