首页 > 文章列表 > 怎么使用Java socket通信模拟QQ实现多人聊天室

怎么使用Java socket通信模拟QQ实现多人聊天室

java socket
472 2023-04-26

怎么使用Java socket通信模拟QQ实现多人聊天室

一、socket通信基本原理

socket 通信是基于TCP/IP ⽹络层上的⼀种传送⽅式,我们通常把TCP和UDP称为传输层。

如上图,在七个层级关系中,我们讲的socket属于传输层,其中UDP是⼀种⾯向⽆连接的传输层协议。UDP不关⼼对端是否真正收到了传送过去的数据。如果需要检查对端是否收到分组数据包,或者对端是否连接到⽹络,则需要在应⽤程序中实现。UDP常⽤在分组数据较少或多播、⼴播通信以及视频通信等多媒体领域。在这⾥我们不进⾏详细讨论,这⾥主要讲解的是基于TCP/IP协议下的socket通信。

socket是基于应⽤服务与TCP/IP通信之间的⼀个抽象,他将TCP/IP协议⾥⾯复杂的通信逻辑进⾏分装,对⽤户来说,只要通过⼀组简单的API就可以实现⽹络的连接。

二、用socket制作一个多人聊天室

对socket通信基本原理明⽩后,那我们就写⼀个最简单的⽰例,制作聊天室。

服务器端Server:

import java.io.*;

import java.net.*;

import java.util.ArrayList;

public class Server{

    public static ServerSocket server_socket;

    public static ArrayList<Socket> socketList=new ArrayList<Socket>();  

    public static void main(String []args){

        try{

            server_socket = new ServerSocket(5000);

            while(true){

                Socket socket = server_socket.accept();

                socketList.add(socket); //把sock对象加入sock集合

                ServerBO_Thread st=new ServerBO_Thread(socket,socketList); //初始化多线程

                st.start();//启动多线程

            }

        }catch(Exception ex){

            ex.printStackTrace();

        }finally{

            try{

                if(server_socket!=null){

                    server_socket.close();

                }

            }catch(Exception ex){

                ex.printStackTrace();

            }

        }

    }

    public void encryptWrite(String src,DataOutputStream output)throws IOException{

        //将一个字符串转化为字符数组

        //System.out.println(src);

        char[] char_arr = src.toCharArray();

        //加密操作

        for(int i = 0;i<char_arr.length;i++){

            output.writeChar(char_arr[i]+13);

        }

        //用作结束标志符

        output.writeChar(2333);

        output.flush();

    }

    //读取并解密

    public String readDecrypt(DataInputStream input)throws IOException{

        String rtn="";

        while(true){

            int char_src =input.readChar();

            if(char_src!=2333){

                rtn=rtn+(char)(char_src-13);

            }else{

                break;

            }

        }

        return rtn;

    }

}

class ServerBO_Thread extends Thread{

    Socket client = null;

    ArrayList<Socket> clients;

    ServerBO_Thread(Socket s,ArrayList<Socket> ss){//初始化

        client=s;

        clients=ss; 

    }

    public void run(){

        DataInputStream input = null;

        DataOutputStream output =null;

        try{

            input = new DataInputStream(client.getInputStream());

            Server bo = new Server();

            String receive=null;

            String send=null;

            while(true){//监视当前客户端有没有发来消息

                if(!client.isClosed()){

                    receive=bo.readDecrypt(input);

                    clients.trimToSize();

                    String[] param = receive.split("&");

                    if(")start".equals(param[1])){    //分析客户端发来的内容

                        send = param[0]+"进入聊天室";

                    }else{

                        send = param[0]+"说:    "+param[1];

                    }

                    if(!("3333".equals(param[1]))){//3333为退出聊天室信号

                        for(Socket socket:clients){ //遍历socke集合 

                            //把读取到的消息发送给各个客户端  

                            if(!socket.isClosed()){

                                output = new DataOutputStream(socket.getOutputStream());

                                bo.encryptWrite(send,output);

                            }

                        }  

                    }else{//如果有客户端退出

                        for(Socket socket:clients){ //遍历socke集合 

                                if(socket!=client){//告诉其他人此人退出聊天室

                                    if(!(socket.isClosed())){

                                        output = new DataOutputStream(socket.getOutputStream());

                                        bo.encryptWrite(param[0]+"已退出聊天室",output);

                                    }

                                }

                            }

                        output = new DataOutputStream(client.getOutputStream());

                        bo.encryptWrite("3333",output);//返回信号给要退出的客户端,然后关闭线程

                        client.close();

                        input.close();

                        output.close();

                    }

                }else{

                    break;

                }

            }

        }catch(Exception ex){

            ex.printStackTrace();

        }

    }

}

客户端:

import java.io.IOException;

import java.util.Scanner;

import java.net.*;

import java.io.*;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.io.BufferedWriter;

import java.io.BufferedReader;

import java.io.DataOutputStream;

public class People{

//服务端ip

    public  String ip = "127.0.0.1";

    //服务端端口

    public  int port = 5000;

    public  DataOutputStream output = null;

    public  Socket socket = null;

    public  DataInputStream input = null;

    public  Scanner sc =new Scanner (System.in);

    public  String send ;

    public  String receive;

    public  String name;

    public String sd = null;

    public static void main(String[]aa){

        People po = new People();

        po.start();

    }

    public void start(){

        try{

            System.out.println("*******欢迎使用匿名聊天室!**********");

            System.out.println("请输入你将要使用的昵称:");

            name=sc.nextLine();//获取昵称

            socket = new Socket(ip,port);

            output=new DataOutputStream(socket.getOutputStream());

            input = new DataInputStream(socket.getInputStream());

            send = name+"&)start";//把昵称发送到server 告诉所有人有新成员加入聊天室

            System.out.println("(如果要退出聊天室请输入“3333”!)");

            System.out.println("*******成功进入匿名聊天室!**********");

            System.out.println("");

            encryptWrite(send,output);

            Out out=new Out(output,name,input,socket);

            out.start();//启动发送聊天内容的多线程

            while(true){    

                String receive = readDecrypt(input);

                if("3333".equals(receive)){//如果收到“3333”则退出聊天室

                    System.out.println("*******成功退出匿名聊天室!**********");

                    input.close();

                    output.close();

                    socket.close();

                    System.exit(0);

                }

                System.out.println(receive);

            }

        }catch(Exception ex){

                ex.printStackTrace();

        }finally{

            try{

                if(socket!=null) socket.close();

                input.close();

                output.close();

            }catch(Exception ex){

                ex.printStackTrace();

            }

        }    

    }

    public void encryptWrite(String src,DataOutputStream output)throws IOException{

        //将一个字符串转化为字符数组

        char[] char_arr = src.toCharArray();

        //加密操作

        for(int i = 0;i<char_arr.length;i++){

            output.writeChar(char_arr[i]+13);

        }

        //用作结束标志符

        output.writeChar(2333);

        output.flush();

    }

    //读取并解密

    public String readDecrypt(DataInputStream input)throws IOException{

        String rtn="";

        while(true){

            int char_src =input.readChar();

            if(char_src!=2333){

                rtn=rtn+(char)(char_src-13);

            }else{

                break;

            }

        }

        return rtn;

    }

}

class Out extends Thread {

    public DataOutputStream output;

    public DataInputStream input;

    public static String name;

    public Socket socket;

    public  Scanner sc =new Scanner (System.in);

    Out(DataOutputStream ot,String n,DataInputStream it,Socket socket){

        output=ot;

        input=it;

        name=n;

    }

    public void run(){

        People po = new People();

        try{

            while(true){

                String send=sc.nextLine();//获取用户输入

                String send2=name+"&"+send;//把聊天内容打包成约定形式

                po.encryptWrite(send2,output);

            }

        }catch(Exception ex){

            ex.printStackTrace();

        }finally{

            System.out.println("sfef");

        }

    }

}

三、实现效果