用java实现模拟聊天室

本案例模拟聊天室,有着群发和私聊的功能,一切都在console中进行,没有界面,采用oop思想,封装操作

代码如下:

服务器端:服务端需要连接多个客户端,因此需要循环监听,每次连接一个客户端创建一个Channel线程,然后再次阻塞式监听。

package com.chatroot.java;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;
public class Chat {
    private static CopyOnWriteArrayList<Channel> list = new CopyOnWriteArrayList<Chat.Channel>();//线程安全容器
    private static int count = 0;
    public static void main(String[] args) throws IOException {
        System.out.println("-----服务器端-----");
        ServerSocket server = new ServerSocket(9999);
        while(true) {
            Socket client = server.accept();
            Channel c = new Channel(client);
            list.add(c);
            count++;//记录连接客户端的数目
            System.out.println("一个客户端建立连接");
            System.out.println("当前客户端数目为:"+count);
            new Thread(c).start();
        }
        
        
    }
    static class Channel implements Runnable{
        private DataInputStream dis = null;
        private DataOutputStream dos = null;
        private Socket client;
        private String name;
        private boolean isRunning;
        public Channel(Socket client) {
            this.client = client;
            try {
                isRunning = true;
                dis = new DataInputStream(client.getInputStream());
                dos = new DataOutputStream(client.getOutputStream());
                this.name = receive();
                send("欢迎进入天地聊天室");
                sendOther("欢迎"+this.name+"的加入",true);
            } catch (IOException e) {
                release();
            }
        }
        //接受消息
        private String receive() {
            String msg = "";//避免空指针
            try {
                msg = dis.readUTF();
            } catch (IOException e) {
                release();
            }
            return msg;
        }
        //发送消息
        private void sendOther(String msg,boolean isSys) {
            boolean isPrivate = msg.startsWith("@");
            if(isPrivate) {
                int index = msg.indexOf(":");
                String target = msg.substring(1, index);
                String data = msg.substring(index+1);
                for(Channel other:list) {
                    if(other.name.equals(target)) {
                        other.send(this.name+"悄悄的对您说"+data);
                        break;
                    }
                }
                
            }else {
                for(Channel other:list) {
                    if(other==this) {
                        continue;
                    }
                    if(isSys) {
                        other.send(msg);
                    }else {
                        other.send(this.name+"说:"+msg);
                    }
                    
                }
            }
            
        }
        private void send(String msg) {
            try {
                dos.writeUTF(msg);
                dos.flush();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        //释放资源
        private void release() {
            isRunning = false;
            CloseUnits.close(dis,dos,client);
            list.remove(this);
            sendOther(this.name+"退出天地聊天室", true);
            count--;
            System.out.println("当前客户端数:"+count);
        }
        
        @Override
        public void run() {
            while(isRunning) {
                String msg = receive();
                if(!msg.equals("")) {
                    sendOther(msg,false);
                }
                
            }
            
        }
    
    }
}
    
客户端:客户端需要实现读和写独立进行,因此需要多线程,一个线程读,一个线程写,各不干涉。

package com.chatroot.java;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
    public static void main(String[] args) throws UnknownHostException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("----客户端----");
        System.out.print("请输入用户名:");
        String name = br.readLine();
        Socket client = null;
        try {
            client = new Socket("localhost",9999);
        }
        catch (Exception e) {
            System.out.println("服务器已经关闭");
        }
        new Thread(new Send(client,name)).start();
        new Thread(new Receive(client)).start();
        
    }
}

分别封装读发送和接受操作

发送端:

package com.chatroot.java;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;


public class Send implements Runnable{
    private DataOutputStream dos;
    private BufferedReader br;
    private String msg;
    private String name;
    private Socket client;
    public Send(Socket client,String name) {
        try {
            this.client = client;
            this.name = name;
            dos = new DataOutputStream(client.getOutputStream());
            br = new BufferedReader(new InputStreamReader(System.in));
            send(name);
        } catch (IOException e) {
            release();
        }
    }
    @Override
    public void run() {
        boolean isRunning = true;
        while(isRunning) {
            msg = getStrFromConsole();
            if(!msg.equals("")) {
                send(msg);
            }
        }
    }
    public String getStrFromConsole() {
        String msg = "";
        try {
            msg = br.readLine();
        } catch (IOException e) {
            return "";
        }
        return msg;
    }
    public void send(String msg) {
        try {
            dos.writeUTF(msg);
            dos.flush();
        } catch (IOException e) {
            release();
        }
        
    }
    public void release() {
        CloseUnits.close(br,dos,client);
        System.out.println("服务器已经关闭");
    }

}
接受:

package com.chatroot.java;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

public class Receive implements Runnable{

    private DataInputStream dis;
    private String msg;
    private Socket client;
    public Receive(Socket client) {
        try {
            this.client = client;
            dis = new DataInputStream(client.getInputStream());
        } catch (IOException e) {
            release();
        }
    }
    @Override
    public void run() {
        boolean isRunning = true;
        while(isRunning) {
            try {
                msg = dis.readUTF();
                System.out.println(msg);
            } catch (IOException e) {
                isRunning = false;
                release();
            }
        }

    }
    public void release() {
        CloseUnits.close(dis,client);
    }
}
将流和资源释放独立封装

package com.chatroot.java;

import java.io.Closeable;
import java.io.IOException;

public class CloseUnits {
    public static void close(Closeable...closeables) {
        for(Closeable target:closeables) {
            try {
                target.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
 

猜你喜欢

转载自blog.csdn.net/demonandyu/article/details/88930976