JAVA网络编程——双用户聊天室实现

  • Post author:
  • Post category:java




实现方案

TCP + 多线程



基本说明



user1

user1 实际上是作为服务器端,在本机暴露9999端口,使用accept()函数实现监听,需要先开始user1的程序,再开启user2程序。

user1有类 user1_send 和 user1_listen 分别负责发送和监听。



user2

user2 实际上是作为客户端,使用Socket(“127.0.0.1”,9999)设置目标地址和端口,发送连接请求。

user2有类 user2_send 和 user2_listen 分别负责发送和监听。



代码实现

user1.java

public class user1 {
    public static void main(String[] args) throws IOException {
        System.out.println("======用户1已上线=======");
        ServerSocket serverSocket = new ServerSocket(9999);

        //当没有接受到套接字请求时,程序阻塞在accept()函数处,
        //一旦接收到套接字请求,则开启相应的监听和发送线程,并且进行下一个循环,建立新的套接字
        while (true){
            //不断接收客户请求,为每一个客户创建一个独立的线程去处理每个客户的请求
            Socket socket = serverSocket.accept();
            new Thread(new user1_listen(socket)).start();
            new Thread(new user1_send(socket)).start();
        }

    }
}

//用来监听user2的请求
class user1_listen implements Runnable{

    private Socket socket;

    public user1_listen(Socket socket) {
        this.socket = socket;
    }

    public void run() {

        try {
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());

            while (true){
                System.out.println(ois.readObject());
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //当客户断开连接或出现异常,服务器的socket需要断开,没有必要保持连接而浪费资源
            try {
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

//用来发送消息
class user1_send implements Runnable{

    private Socket socket;

    public user1_send(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            Scanner scanner = new Scanner(System.in);
            while(true){
                //读取键盘输入
                String string  = scanner.nextLine();
                //将内容写入通信管道
                oos.writeObject("user1发送:"+string);
                oos.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

user2.java

package com.bhy.qq;

import org.json.simple.JSONObject;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class user2 {
    private  static Socket socket;

    private static boolean connection_state = false;

    public static void main(String[] args) {
        connect();
        System.out.println("======用户2已上线=======");
        if(connection_state){
            new Thread(new user2_listen(socket)).start();
            new Thread(new use2_send(socket)).start();
        }

    }

    //连接user1
    public static void connect(){
        try {
            socket = new Socket("127.0.0.1",9999);
            connection_state = true;
        } catch (IOException e) {
            e.printStackTrace();
            connection_state=false;
        }
    }
}



//用来接收user1传来的信息
class user2_listen implements Runnable{

    private Socket socket;

    public user2_listen(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            while (true){
                System.out.println(ois.readObject());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

//用来发送消息
class use2_send implements Runnable{
    private Socket socket;

    public use2_send(Socket socket) {
        this.socket = socket;
    }

    public void run() {

        try {
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            Scanner scanner = new Scanner(System.in);
            while(true){
                //读取输入
                String string = scanner.nextLine();
                oos.writeObject("user2发送:"+string);
                oos.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}



测试

先开启user1,再开启user2。

user1先发送 hello,user2 , I ’ m user1!!

user2发送 hello , I ’ m user 2! ^*^

user1窗口

user2窗口



拓展——增加user3

此外,可以无限增加用户与user1通信,因为user1是服务端,并且不断有新的套接字监听,可以建立多个套接字连接。

关键代码如下

user1.java

//当没有接受到套接字请求时,程序阻塞在accept()函数处,
//一旦接收到套接字请求,则开启相应的监听和发送线程,并且进行下一个循环,建立新的套接字
while (true){
    //不断接收客户请求,为每一个客户创建一个独立的线程去处理每个客户的请求
    Socket socket = serverSocket.accept();
    new Thread(new user1_listen(socket)).start();
    new Thread(new user1_send(socket)).start();
}



测试

user3.java

和user2代码几乎一样,把代码中的 2 改成 3 即可

public class user3{
    private  static Socket socket;

    private static boolean connection_state = false;

    public static void main(String[] args) {
        connect();
        System.out.println("======用户3已上线=======");
        if(connection_state){
            new Thread(new user3_listen(socket)).start();
            new Thread(new use3_send(socket)).start();
        }

    }

    //连接user1

    public static void connect(){
        try {
            socket = new Socket("127.0.0.1",9999);
            connection_state = true;
        } catch (IOException e) {
            e.printStackTrace();
            connection_state=false;
        }
    }
}


class user3_listen implements Runnable{

    private Socket socket;

    public user3_listen(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            while (true){
                System.out.println(ois.readObject());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class use3_send implements Runnable{
    private Socket socket;

    public use3_send(Socket socket) {
        this.socket = socket;
    }

    public void run() {

        try {
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            Scanner scanner = new Scanner(System.in);
            while(true){
                String string = scanner.nextLine();
                oos.writeObject("user3发送:"+string);
                oos.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果:

user3输入

3testing

user2输入

2testing



但是新的问题会出现,user1发送的消息会随机发送给user2或user3,因为此时user1同时有两个发送线程,不知道发送的时候会用到哪一个。在这里不给出解决方案(主要不会/(ㄒoㄒ)/~~

所以user1只能实现接收多方信息的功能,不能精准发送消息



版权声明:本文为qq_45915904原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。