一、概述

        前一篇博客我们了解了TCP通信协议的基本原理以及实现过程,因此需要更进一步,即实现双方都能够实时通信。

二、原理

        在上一篇博客中说过,使用Java Socket模型中的socket 对象去监听某个对象的连接,通过获取该对象的socket获取流信息,但问题在于如何实现消息的实时收发?

        1、单线程收发消息的不足:

                当我们创建一个客户端到服务段的socket连接之后,需要设置对象的IO流,但在主函数中,这些方法是被线性执行的,因此两端的IO流都是依此执行的,每个方法必须等待上一个方法结束后才能执行,这样收发消息的效率比较低。因此我们可以通过多线程将这些功能独立出来,每个线程只负责运行自己的功能,这样就可以突破线性执行的缺点。

        2、实现过程:

                在创建对象的IO流时,先将对应的功能放到线程中,并通过无限循环该功能实现消息的实时收发。

三、代码实现

        1、服务器对象

public class Server {
    //初始化服务器的端口以及socket对象
    ServerSocket socket = null;
    int port = 58888;

    //初始化服务器
    public void initServer(){
        try {
            socket = new ServerSocket(port);
        } catch (IOException e) {
            throw new RuntimeException (e);
        }
    }

    //检测端口是否有对象连接
    public Socket listener(){
        try {
            return socket.accept();
        } catch (IOException e) {
            throw new RuntimeException (e);
        }
    }

    public void init(){
        initServer();
        Socket newSocket = listener();
        //IO流线程初始化并启动
        ReciveMessageThread reciveMessageThrea = new ReciveMessageThread(newSocket);
        SendMessageThread sendMessageThread = new SendMessageThread(newSocket);
        reciveMessageThrea.start();
        sendMessageThread.start();
    }


    public static void main(String[] args) {
        new Server().init();
    }

}

        2、IO流线程

//消息接收端
public class ReciveMessageThread extends Thread{
    //初始化对象
    Socket socket = null;
    InputStream in = null;
    static String returnMsg;

    public ReciveMessageThread(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            in = socket.getInputStream();
            System.out.println("in初始化成功");
        } catch (IOException e) {
           throw new RuntimeException(e);
        }
        while (true){
            System.out.println("开始接收数据");
            try {
                int msgLen = in.read();
                byte [] msg = new byte[msgLen];
                in.read(msg);
                returnMsg = new String(msg , 0 , msgLen);
            } catch (IOException e) {
                throw new RuntimeException (e);
            }
        }
    }
}
//消息发送端
public class SendMessageThread extends Thread{
    Socket socket = null;
    OutputStream out = null;

    public SendMessageThread(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            out = socket.getOutputStream();
            System.out.println("out初始化成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
        while (true){
            System.out.println("请输入发送的信息");
            Scanner sc = new Scanner(System.in);
            String msg = sc.next();
            MessageEncode messageEncode = new MessageEncode(msg);
            try {
                out.write(1);
                out.write(messageEncode.encoding().length);
                out.write(messageEncode.encoding());
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

        3、消息编解码

//消息编码
public class MessageEncode {
    String msg;

    public MessageEncode(String msg){
        this.msg = msg;
    }

    //将消息转换为字节并存入字节数组
    public byte[] encoding(){
        byte [] data = this.msg.getBytes();

        return data;
    }
}
//消息解码
public class MessageDecode {
    InputStream inputStream;

    public MessageDecode(InputStream inputStream){
        this.inputStream = inputStream;
    }

    //通过IO流获取发送的数组,解码并输出
    public String decoding(){
        byte [] reciveMsg = new byte[1024];
        try {
            this.inputStream.read(reciveMsg);
            int len = reciveMsg.length;
            System.out.println(len);
            String newMsg = new String(reciveMsg , 0 , len);
            return newMsg;
        } catch (IOException e) {
            throw new RuntimeException (e);
        }
    }
}

        4、客户端连接

public class Client_A {

    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1" , 58888);
            InputStream in = socket.getInputStream();
            byte b [] = new byte[1024];
            while (true){
                int len = 0;
                len = in.read(b);
                String newStr = new String(b , 0 , len);
                System.out.println(newStr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

四、运行效果

服务器监听到客户端连接

java 进程 通讯 java通信_初始化

服务器端消息发送

java 进程 通讯 java通信_java_02

 

 客户端消息接收

java 进程 通讯 java通信_tcp/ip_03