Java丨即时聊天程序的实现 - Go语言中文社区

Java丨即时聊天程序的实现


 

继续昨天的代码丨多客户端通信实现

 

想要建立多客户端即时通信,必须具有这几个条件(类);

1、客户端;

2、服务器;

3、消息类(数据封包);

4、消息类型。

Demo;

package Task.demo;

import java.io.Serializable;

public class Message implements Serializable {
    private String from;//发送者
    private String to;//接收者
    private int type;//消息类型
    private  String info;//消息内容

    public Message(){

    }


    public Message(String from, String to, int type, String info) {
        this.from = from;
        this.to = to;
        this.type = type;
        this.info = info;
    }

    public String toString() {
        return "Message{" +
                "from='" + from + ''' +
                ", to='" + to + ''' +
                ", type=" + type +
                ", info='" + info + ''' +
                '}';
    }

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}
package Task.demo;

public final class MessageType {
    public  static final int TYPE_LOGIN=0x1;//登录消息类型
    public  static final int TYPE_SEND=0x2;//正常聊天的消息类型

}
package Task.demo;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {//服务器

    public static void main(String[] args){
        //用来保存与客户端通信的用户线程(UserThread)
        Vector<UserThread> vector=new Vector<>();
        ExecutorService es= Executors.newFixedThreadPool(5);
        //TCP协议
        try {
            ServerSocket server = new ServerSocket(9988);
            System.out.println("服务器已启动,正在等待客户端连接");
            while (true){
                Socket socket = server.accept();//等待客户端连接,此方法会阻塞
                UserThread user=new UserThread(socket,vector);
                //把runnable接口作为一个任务,传入线程池中,
                // 那么线程池会启动一个线程来执行这个任务
                es.execute(user);

            }
        }catch (IOException e){
            e .printStackTrace();
        }
    }
}
//处理客户端消息的线程
class UserThread implements  Runnable{
    private String name;//代表的是客户端唯一的昵称
    private Socket socket;//代表此线程任务服务的客户端socket
    private Vector<UserThread> vector;
    private ObjectInputStream in;//对象输入流,读取
    private ObjectOutputStream out;//对象输出流,写入
    private boolean flag=true;//循环的标记

    public UserThread(Socket socket, Vector<UserThread> vector) {
        this.socket = socket;
        this.vector = vector;
        this.vector.add(this);
    }

    public void  run(){
        //1、谁连接了
        System.out.println("客户端"+socket.getInetAddress().getHostAddress()+"已连接");
        //2、初始化输入输出流
        try {
            in = new ObjectInputStream(socket.getInputStream());
            out = new ObjectOutputStream(socket.getOutputStream());
            //3、循环读取消息
            while (flag) {
                Message m = (Message) in.readObject();

                //4、判断消息的类型
                switch (m.getType()) {
                    case MessageType.TYPE_SEND:
                        String to = m.getTo();
                        int size = vector.size();
                        UserThread ut;
                        for (int i = 0; i < size; i++) {
                            ut = vector.get(i);
                            if (to.equals(ut.name) && ut != this) {
                                ut.out.writeObject(m);//找到了客户端所对应的中转线程,
                                // 通过中转线程把消息发送给客户端
                                break;
                            }
                        }
                        break;
                    case MessageType.TYPE_LOGIN:
                        name = m.getFrom();
                        m.setInfo("欢迎你:");
                        out.writeObject(m);
                        break;
                }

            }
            in.close();
            out.close();
            //5、根据不同的消息类型做相应的处理
        }catch (EOFException e){
            flag=false;
            System.out.println("客户端"+socket.getInetAddress().getHostAddress()+"已断开");//提示
        }catch (IOException e){
            e.printStackTrace();
        }catch (ClassNotFoundException e){
            e.printStackTrace();
            flag=false;
        }
    }

}
package Task.demo;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Client {//客户端
    public static void main(String[] args){

        Scanner input =new Scanner(System.in);
        ExecutorService es= Executors.newSingleThreadExecutor();//单线程
        try{
            Socket socket = new Socket("Localhost",9988);
            System.out.println("服务器连接成功");

            ObjectOutputStream out =new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream in =new ObjectInputStream(socket.getInputStream());

            //====模拟用户登录====
            //向服务器发送登录消息
            System.out.println("请输入昵称:");
            String name=input.nextLine();
            //封装数据包
            Message m = new Message (name, null , MessageType.TYPE_LOGIN, null);
            out.writeObject(m); //向服务器发消息
            //从服务器读取消息
            m = (Message) in.readObject();
            System. out . println(m. getInfo()+m. getFrom());
            //=====模拟用户登录结束=====
            //启动读取消息的线程
            es.execute(new ReadInfoThread(in));
            //通过主线程来实现发送消息
            boolean flag=true;
            while (flag){
                m=new Message();
                System.out.println("to:");
                m.setTo(input.nextLine());
                System.out.println("Info:");
                m.setInfo(input.nextLine());
                m.setFrom(name);
                m.setType(MessageType.TYPE_SEND);
                out.writeObject(m);
            }
        }catch (IOException e){
            e.printStackTrace();
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}

class ReadInfoThread implements  Runnable{
    private ObjectInputStream in;
    private boolean flag=true;
    public ReadInfoThread (ObjectInputStream in) {
        this.in = in;
    }
    public  void  setFlag(boolean flag){
        this.flag=flag;
    }
    public void run() {
        while (flag){
            try{
                Message message=(Message) in.readObject();
                System.out.println("["+message.getFrom()+"]对我说:"+message.getInfo());
            }catch (IOException e){
                e.printStackTrace();
            }catch (ClassNotFoundException e){
                e.printStackTrace();
            }
        }
        if(in!=null){
            try{
                in.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }

    }
}

运行结果:

服务器

客户端 1

 

客户端2

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_45290108/article/details/100148594
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 17:41:03
  • 阅读 ( 799 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢