JAVA网络编程模拟多人聊天(多线程实现)

一.要求
要求:

  • 使用ServerSocket启动8080端口,监听客户端连接
  • 将与客户端连接的Socket保存在Vector中
  • 开启一个接收该客户端消息的线程
  • 客户端开启发送消息和接收消息线程
    二.代码实现
    1.服务器端代码
package problem03;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;

/**
 * 要求:
 *      使用ServerSocket启动8080端口,监听客户端连接
 *      将与客户端连接的Socket保存在Vector中
 *      开启一个接收该客户端消息的线程
 */
public class Server implements Runnable{
    ServerSocket ss = null;
    int port = 8080;
    static Vector v = new Vector<>();  //存储Socket信息

    public  Server(int port) {  //带参构造,指定ServerSocket绑定端口号
        this.port = port;
    }

    @Override
    public void run() {
        try{
            ss = new ServerSocket(port);   //绑定端口号

            while (true){
                Socket cs = ss.accept();  //开启监听
                v.add(cs);   //将当前Socket信息存储到集合
                new Rec_Sen_Thread(cs).start();  //开启服务器消息接收并转发线程
            }

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






    class Rec_Sen_Thread extends Thread{ //服务器接收消息并转发
        Socket cs = null;

        public Rec_Sen_Thread(Socket cs) {
            this.cs = cs;
        }

        @Override
        public void run() {
            DataInputStream dis = null;  //输入流
            try {
                dis = new DataInputStream(cs.getInputStream());
                String str = null;
                while((str=dis.readUTF()) != null){ //读取数据
                    for (Socket socket : v) { //轮询发送
                        if (cs != socket) {  //不给消息来源客户端转发它自己的消息
                            DataOutputStream dos =
                                    new DataOutputStream(socket.getOutputStream());
                            dos.writeUTF(str);  //转发消息
                            dos.flush();
                            //System.out.println(str);
                        }
                    }

                }

/*
                byte[] bys = new byte[1024*8];
                int len = 0;
                while ((len=dis.read()) != -1){
                    for (Socket socket : v) {
                        if (cs != socket) {
                            DataOutputStream dos =
                                    new DataOutputStream(socket.getOutputStream());
                            dos.write(bys,0,len);
                        }
                    }
                }
*/
            } catch (IOException e) {
                e.printStackTrace();
            }finally {  //释放资源
                if(dis != null){
                    try {
                        dis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }






    public static void main(String[] args) {
        Server server = new Server(8080);
        new Thread(server).start();  //开启线程

    }


}

2.客户端代码

package problem03;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;

/**
 * 要求:
 *      客户端开启发送消息和接收消息线程
 */

public class Client implements Runnable{
    Socket cs = null;
    String host;   //远端服务器名称和端口
    int port;

    public Client(String host, int port){
        this.host = host;
        this.port = port;
    }
    @Override
    public void run(){
        try{
            cs = new Socket(InetAddress.getByName(host), port);//建立连接

            new RecThread(cs).start(); //解决接收数据时产生的阻塞
            new SendThread(cs).start();
        }catch(Exception e){
            e.printStackTrace();
        }
    }






    class RecThread extends Thread{ //接收消息线程
        Socket cs = null;

        public RecThread(Socket cs){
            this.cs = cs;
        }

        public void run(){
            String str;
            DataInputStream dis = null;
            try {
                dis = new DataInputStream(cs.getInputStream());//输入流
                while((str = dis.readUTF())!=null){ // 网络阻塞点,读取数据
                    System.out.println(str);   //消息打印在控制台,模拟客户端收到消息
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {  //释放资源
                if(dis!=null){
                    try {
                        dis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            }

        }
    }






    class SendThread extends Thread{  //客户端发送线程
        Socket cs = null;
        public SendThread(Socket cs){
            this.cs = cs;
        }

        public void run(){
            String str;
            DataOutputStream dos = null;
            try{
                Scanner input = new Scanner(System.in);  //客户端输入消息
                dos = new DataOutputStream(cs.getOutputStream());//输出流
                while((str = input.next())!=null){ //键盘阻塞
                    if("886".equals(str)){ //客户端结束聊天,主动断开Socket连接
                        dos.writeUTF("Byebye!");
                        dos.flush();
                        break;
                    }
                    dos.writeUTF(str);  //输出
                    dos.flush();   //立即从缓冲发送

                }
            }catch(Exception e){
                e.printStackTrace();
            }finally {  //释放资源
                if(dos!=null){
                    try {
                        dos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }





    public static void main(String [] args){
        Client c = new Client("localhost", 8080);
        new Thread(c).start();

    }

}

三.运行结果

三个客户端界面的结果如图:

JAVA网络编程模拟多人聊天(多线程实现)_第1张图片
JAVA网络编程模拟多人聊天(多线程实现)_第2张图片
JAVA网络编程模拟多人聊天(多线程实现)_第3张图片

你可能感兴趣的:(JAVA网络编程)