欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于Socket编程的网络聊天室

程序员文章站 2022-06-30 19:15:34
...

1.项目简介:
基于Socket编程的网络聊天室
2.功能描述:
可以实施多个用户的注册,群发和私聊:
3.具体实现流程:
客户端实现流程:
1.客户端的功能可以进一步细化为:
对外发送信息:
接受其他客户端的信息:
由于发送和接受的功能应该是独立的,所以使用两个线程来分别实现:
1.发送线程:
内部主要实现原理是通过获取sokcet输出流,通过输出流发送信息
2.如果有Bye字样则关闭Socket退出聊天

public class Write implements Runnable{
    private Socket socket;

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

    public void run() {
        try {
        	//获取输出流
            PrintStream out=new PrintStream(socket.getOutputStream());
            Scanner scanner = new Scanner(System.in);
            String msg=null;
            while(true) {
                if(scanner.hasNext()) {
                    msg = scanner.next();
                }
                out.println(msg);
                if(msg.contains("Bye")){
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

接受其他客户端的信息:
流程:
获取输入流来读取从服务器发送的信息:

class Read implements Runnable{
    private Socket socket;

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

    public void run() {
        Scanner scanner= null;
        try {
            scanner = new Scanner(socket.getInputStream());
            while(true){
                System.out.println("等待客户端发来的消息");
                String str=null;
                if(scanner.hasNext()){
                    System.out.println(scanner.next());
                }
                if(socket.isClosed()){
                    break;
                }


            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}

服务器实现流程:
一个中转站的功能:将发送来的信息进行分类,来达到注册、群发、私聊的功能
public class Services {
private static Map<String,Socket> map=new ConcurrentHashMap<String, Socket>();
static private class RealServices implements Runnable{
private Socket socket;

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

    public void run() {
        try {
            Scanner in=new Scanner(socket.getInputStream());
            String msg=null;
            while(true){
                if(in.hasNext()) {
                    msg = in.next();
                }
                Pattern pattern = Pattern.compile("\r");
              java.util.regex.Matcher matcher = pattern.matcher(msg);
              //如果以userName开头则是注册,即将所有用户信息存放在map中
              if(msg.startsWith("userName")){
                  String username=msg.split(":")[1];
                  register(username);
                    continue;
              }
              //G开头说明是群聊
              if(msg.startsWith("G")){
                  String send=msg.split(":")[1];
                  group(send);
              }
              //收到数据已P开头说明是私聊
              if (msg.startsWith("P")){
                  String username=msg.split(":")[1].split("\\-")[0];
                  String send=msg.split("\\-")[1];
                  privateSend(username,send);
              }
              if(msg.contains("Bye")){
                  Set<Map.Entry<String, Socket>> entries = map.entrySet();
                  Iterator<Map.Entry<String,Socket>> iterator=entries.iterator();
                  String username=null;
                  Socket socket=null;
                  while(iterator.hasNext()){
                      Map.Entry<String,Socket> i=iterator.next();
                      username=i.getKey();
                       socket=i.getValue();
                      if(socket==this.socket){
                          iterator.remove();
                      }
                  }
                  group(username+"退出群聊,当前聊天室还剩"+map.size());
                  System.out.println(username+"退出群聊");
              }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private void register(String username) throws IOException {
        if(map.containsKey(username)){
            System.out.println("当前用户已存在");
        }else {
            map.put(username,socket);
            group("欢迎"+username+"加入聊天室,当前聊天室人数:"+map.size());
            System.out.println("欢迎"+username+"加入聊天室,当前聊天室人数:"+map.size());

        }
    }
	//遍历map集合将每一个数据发送出去
    private  void group(String send) throws IOException {
        Set<Map.Entry<String, Socket>> entries = map.entrySet();
        Iterator<Map.Entry<String,Socket>> iterator=entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String,Socket> i=iterator.next();
            Socket socket=i.getValue();
            if(socket==this.socket){
                continue;
            }
            PrintStream printStream=new PrintStream(socket.getOutputStream());
            printStream.println(send);
        }

    }
    //私聊获取指定用户的Socket,创建连接发送
    private  void privateSend(String username, String send) throws IOException {
        Socket to=map.get(username);
        if(to==null){
            PrintStream out=new PrintStream(socket.getOutputStream());
            out.println("当前用户不存在");
        }else {
            PrintStream out=new PrintStream(to.getOutputStream());
            out.println("发送信息: "+send);
        }
    }
}