Java网络学习——基于TCP/IP的聊天程序

网络聊天室

这是一个基于TCP/IP协议的多人网络聊天室,客户端发送消息给服务端,服务端再将消息发送给所有的客户端,实现多人群聊。需要源码的请参见这里,提取码:9527。

服务端

Server
创建服务,启动聊天线程。

public class Server {

    /**
     * 对外提供的端口号
     */
    private int port;
    /**
     * 用于记录所有产生的socket对象
     */
    public volatile static List<Socket> client = new ArrayList<>();

    public Server(int port) {
        this.port = port;
    }

    public void startServer() {
        try {
            //创建服务
            ServerSocket server = new ServerSocket(port);
            Tools.tips("服务已开启,等待连接。。。");
            while (true) {
                //监听客户端连接
                Socket s = server.accept();
                //将获取的Socket对象添加到集合中
                client.add(s);
                Tools.tips("客户端已连接:" + Tools.ip(s));
                //启动聊天服务线程
                new TalkingServer(s).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        new Server(5678).startServer();
    }
}

MsgServer
消息接收转发服务线程,用于接收客户端发送的消息,再将其转发给所有的客户端。

/**
 * 消息接收转发线程
 */
public class MsgServer extends Thread {

    private Socket s;

    public MsgServer(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {
        try {
            //读取接收到的来自Socket的消息
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            //临时变量,用于接收每次读取的文本消息
            String msg = null;
            while ((msg = br.readLine()) != null) {
                for (Socket s : Server.client) {

                    String content = Tools.date(System.currentTimeMillis()) + " " + Tools.host(s) + ":" + msg;

                    Tools.sendMsg(s.getOutputStream(), content);
                }
            }
        } catch (IOException e) {
            Tools.tips("客户断开连接:" + Tools.ip(s));
            //从集合中移除该对象
            Server.client.remove(s);
        }
    }
}

客户端

Client
客户端:与服务端建立连接,进行消息发送,并同步启动消息接收线程,实现发消息的同时接收消息。

public class Client {

    /**
     * 远程服务的ip地址
     */
    private String ip;
    /**
     * 远程服务应用的端口
     */
    private int port;

    public Client(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

    public void startChat() {

        try {
            Socket s = new Socket(ip, port);
            MsgReceiver mr = new MsgReceiver(s);
            mr.setDaemon(true);
            mr.start();

            //获取文本扫描对象
            Scanner sc = new Scanner(System.in);
            OutputStream os = s.getOutputStream();

            String msg = "";
            while (!"quit".equals(msg)) {
                msg = sc.nextLine();
                Tools.sendMsg(os, msg);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        new Client("192.168.7.170", 5678).startChat();
    }
}

MsgReceiver
消息接收线程,用于接收消息,并将聊天记录按日期存入文件中进行保存。

/**
 * 消息接收线程
 */
public class MsgReceiver extends Thread {

    private Socket s;
    private File dir;

    {
        FileSystemView fsv = FileSystemView.getFileSystemView();
        dir = fsv.getHomeDirectory();
    }

    public MsgReceiver(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            //获取Socket中的输入流
            InputStream is = s.getInputStream();
            //将字节输入流转换为字符输出流
            InputStreamReader isr = new InputStreamReader(is);
            //将低级流包装为缓冲流
            br = new BufferedReader(isr);
            String msg = null;
            //循环读取
            while ((msg = br.readLine()) != null) {
                Tools.tips(msg);
                chatRecord(msg, dir);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 保存聊天记录
     */
    public void chatRecord(String msg, File dir) throws IOException {
        //获取当前时间
        LocalDate date = LocalDate.now();
        //获取目录下文件集合
        File[] files = dir.listFiles();
        //定义变量用于标记当前日期的文件是否存在,默认不存在
        boolean b = false;
        if (files != null) {
            for (File f : files) {
                //判断文件存在
                if (f.getName().equals(date.toString() + ".txt")) {
                    //将聊天记录写入文件中
                    writeRecord(f, msg);
                    //标记文件存在
                    b = true;
                }
            }
        }
        //如果文件不存在
        if (!b) {
            String fileName = date.toString() + ".txt";
            //创建当天日期的文件
            File file = new File(dir, fileName);
            //将聊天记录写入文件中
            writeRecord(file, msg);
        }
    }

    /**
     * 将聊天记录写入文件中
     *
     * @param f
     * @param msg
     * @throws IOException
     */
    public void writeRecord(File f, String msg) throws IOException {
        //获取文件字节输出流
        OutputStream os = new FileOutputStream(f, true);
        //将字节输出流包装为字符打印流
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));
        //将消息写入
        pw.println(msg);
        //刷新,将缓冲区的字符写入文件中
        pw.flush();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值