网络通信--demo--群聊

群聊实现的关键:

  1. 群聊的思想:客户端发送消息后,所有客户端都可以接收到

  2. 客户端---->服务端(子)---->客户端(online)

  3. online的客户端:需要一个集合存储

package Wechat;

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;

public class Cilent {
    //1.客户端
    public static void main(String[] args) throws Exception {
//        1. 创建客户端的Socket对象(套接字对象),请求与 服务端的连接
        Socket socket = new Socket(InetAddress.getLocalHost(),8888);//"127.0.0.1"
        //创建一个独立的线程,负责从socket中接收服务器发送过来的消息
        ClentReaderThread clentReaderThread = new ClentReaderThread(socket);
        clentReaderThread.start();
//        2. 使用socket对象调用getOutputStream()方法得到字节输出流
        OutputStream os = socket.getOutputStream();
//        3. 使用数据输出流(其他高级流也行,这个最适合)完成数据的发送
        DataOutputStream dos = new DataOutputStream(os);
        //需要实现用户键盘输入什么发送什么,输入"exit"时退出
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入信息:");
            String message = sc.nextLine();
            if("exit".equals(message)){
                System.out.println("客户端已退出!");
                dos.close();
                socket.close();//客户端退出,关闭所有资源
                break;
            }
            dos.writeUTF(message);
            dos.flush();
            dos.writeUTF("客户端发送成功!");
        }
    }
}
package Wechat;

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

public class ClentReaderThread extends Thread{
    //客户端接收读取线程
    private Socket socket;
    //每个子线程拿到套接字
    public ClentReaderThread(Socket socket){
        this.socket = socket;
    }
    //负责描述子线程中该套接字的任务
    @Override
    public void run(){
        //该套接字负责读取客户端的信息;
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            while (true) {
                try {
                    String message = dis.readUTF();//拿到消息,需要把消息分发到每一个客户端包括自己
                    System.out.println(message);
                    System.out.println("-------------------------");
                } catch (Exception e) {
                    System.out.println("自己下线了:" + socket.getRemoteSocketAddress());
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
package Wechat;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server {
    //定义一个集合存放在线的客户端<管道>
    public static List<Socket> onlineSockets = new ArrayList<>();
    //客户端
    public static void main(String[] args) throws Exception {
//        5. 创建ServerSocket的对象,同时为服务端注册端口
        ServerSocket serverSocket = new ServerSocket(8888);
        while (true) {
//        6. 使用serverSocket对象,调用accept方法,等待客户端的连接请求得到socket对象
            Socket socket = serverSocket.accept();//拿到套接字
            onlineSockets.add(socket);//添加上线客户端
            System.out.println("有用户上线了:" + socket.getRemoteSocketAddress());
            new ServerReaderThread(socket).start();//把套接字交给子线程并启动
        }
    }
}

package Wechat;

import java.io.*;
import java.net.Socket;

public class ServerReaderThread extends Thread{
    //服务端读取线程
    private Socket socket;
    //每个子线程拿到套接字
    public ServerReaderThread(Socket socket){
        this.socket = socket;
    }
    //负责描述子线程中该套接字的任务
    @Override
    public void run(){
        //该套接字负责读取客户端的信息;
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            while (true) {
                try {
                    String message = dis.readUTF();//拿到消息,需要把消息分发到每一个客户端包括自己
                    sendMsgToAll(message);
                    System.out.println(message);
                    System.out.println("-------------------------");
                } catch (IOException e) {
                    System.out.println("有用户下线:" + socket.getRemoteSocketAddress());
                    Server.onlineSockets.remove(socket);
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void sendMsgToAll(String message) throws IOException {
        //发送给所有的在线的socket管道<客户端>
        //方向:服务端(子线程)---> socket管道(outputstream输出流发送)
        for (Socket onlinesocket : Server.onlineSockets){
            OutputStream os = onlinesocket.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF(message);
            dos.flush();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值