Java Socket 通信 (四)

前言:经过前三次的学习,今天又深入了一步。组长说,你尝试下传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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值