java-聊天室

客户端:

package homework.chat;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client extends AbstractServerClient{

    public static void main(String[] args) throws IOException {
        Client client = new Client();
        Socket socket = new Socket("localhost", 5000);

        System.out.println("请输入昵称:");
        Scanner s = new Scanner(System.in);
        String name = s.nextLine();
        client.send(1,name, socket.getOutputStream());

        // 从控制台获取输入,向服务器发送信息
        new Thread(()->{
            try (OutputStream out = socket.getOutputStream()) {
                Scanner scanner = new Scanner(System.in);
                while(scanner.hasNextLine()) {
                    String line = scanner.nextLine();
                    // 发送消息
                    // 2 获取用户
                    // 3 内容 群聊
                    // 4 内容 对方名字 私聊
                    // 对命令进行分析
                    char cmd = line.charAt(0);
                    switch(cmd) {
                        case '2':
                            client.send(2, "", out);
                            break;
                        case '3':
                            String content = line.substring(2);
                            client.send(3, content, out);
                            break;
                        case '4':
                            // 4 bbb 你好
                            String c2 = line.substring(2);
                            client.send(4, c2, out);
                            break;
                        default:
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        // 接收服务器返回的响应
        new Thread(()->{
            try (InputStream in = socket.getInputStream();
                OutputStream out = socket.getOutputStream()
            ) {
                client.receive(socket, in, out);
            } catch (IOException e) {
            }
        }).start();
    }


    @Override
    protected void handle(int cmd, String content, Socket socket, InputStream in, OutputStream out) {
        switch (cmd) {
            case 5:
                System.out.println(content);
                break;
            case 6:
                System.out.println(content);
                break;
            case 7:
                System.out.println(content);
                break;
            case 8:
                System.out.println(content);
                break;
        }
    }
}

服务器:

package homework.chat;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server extends AbstractServerClient {

    public static void main(String[] args) {
        Server server = new Server();
        System.out.println("服务器已经开始运行...");
        try {
            ServerSocket serverSocket = new ServerSocket(5000);
            ExecutorService service = Executors.newFixedThreadPool(10);
            while (true) {
                Socket socket = serverSocket.accept();
                // 提交给线程池的一个线程处理任务
                service.submit(() -> {
                    try (InputStream in = socket.getInputStream();
                         OutputStream out = socket.getOutputStream()
                    ) {
                        server.receive(socket, in, out);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // key 是socket, value 是昵称    线程安全的hashmap  Concurrent本意是并发
    private Map<Socket, String> map = new ConcurrentHashMap<>();

    @Override
    protected void handle(int cmd, String content, Socket socket, InputStream in, OutputStream out) throws IOException {
        switch (cmd) {
            case 1:
                map.put(socket, content);
                send(5, "欢迎[" + content + "]来到聊天室", out);
                break;
            case 2:
                send(6, map.values().toString(), out);
                break;
            case 3:
                //  s是所有的socket 对象, value 是昵称
                System.out.println("收到的信息:"+content);
                String nick = map.get(socket);// 得到发送者的昵称
                String c = nick+"说了:"+content;
                map.forEach((s, value)->{
                    try {
                        send(7, c, s.getOutputStream());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
                break;
            case 4:
                // bbb 你好
                String[] array = content.split(" ");
                String n = array[0]; // 对方的名字
                String c2 = array[1]; // 内容
                boolean found = false;
                for (Map.Entry<Socket, String> entry :map.entrySet()) {
                    // 找到了
                    if(entry.getValue().equals(n)) {
                        send(8, map.get(socket)+"对你私聊:"+c2, entry.getKey().getOutputStream());
                        found = true;
                        break;
                    }
                }
                if(!found) {
                    send(8, "抱歉,聊天室没这个人", out);
                }
                break;
        }
    }
}

父类(为了提高代码的复用性)

package homework.chat;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public abstract class AbstractServerClient {

    // cmd 命令类型, content 消息内容,
    public void send(int cmd, String content, OutputStream out) throws IOException {
        // 协议: 就是客户端与服务器端约定的一种规则
        // 第一个字节 : 命令类型
        // 2,3 字节: 内容长度   10
        // 剩下的是内容
        out.write(cmd); // 第一个字节 : 命令类型
        byte[] bytes = content.getBytes("utf-8");
        int length = bytes.length; // 300
        // 0x  23 45
        out.write(0xFF & (length >> 8)); // 发送长度的高位
        out.write(0xFF & length); // 发送长度的低位

        out.write(bytes); // 发送字节内容
    }

    public void receive(Socket socket, InputStream in, OutputStream out) throws IOException {
        while(true) {
            int cmd = in.read();
            if(cmd == -1) break;

            int hi = in.read();
            int lo = in.read();
            int length = (hi << 8) + lo;

            byte[] bytes = new byte[length];
            in.read(bytes);

            String content = new String(bytes, "utf-8");
            // 处理具体处理代码暂未实现  方法()
            handle(cmd, content, socket, in, out);
        }
    }

    // 父类还不知道如何处理 cmd 和 content
    protected abstract void handle(int cmd, String content, Socket socket, InputStream in, OutputStream out) throws IOException;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值