本文实例为大家分享了Java Socket实现聊天室的具体代码,供大家参考,具体内容如下

1 创建登录判断类UserLogin

import java.util.HashSet;
import java.util.Set;

public class UserLogin {

    public static boolean login(String username) {
        Set<String> set = initUser();
        // set中含有该username则登录成功
        return set.contains(username);
    }

    public static Set<String> initUser() {
        Set<String> set = new HashSet<>();
        set.add("111");
        set.add("222");
        set.add("333");
        set.add("444");
        set.add("555");
        return set;
    }
}

2 创建登录服务器LoginServer

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

public class LoginServer {
    public static void main(String[] args) {
        int port = 6666;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("登录服务器已经启动");
            while (true) {
                Socket socket = serverSocket.accept();
                // 接收Client输出的信息(username)
                InputStream inputStream = socket.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String username = bufferedReader.readLine();
                // 调用登录方法,判断是否成功登录
                OutputStream outputStream = socket.getOutputStream();
                PrintStream printStream = new PrintStream(outputStream);
                if (UserLogin.login(username)) {
                    System.out.println(username   "登录成功");
                    // 登录成功输出"true"到Client
                    printStream.println("true");
                } else {
                    System.out.println(username   "登录失败");
                    // 登录失败则输出"false"到Client
                    printStream.println("false");
                }
                printStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3 创建聊天服务器ChatServer

import com.socket.socketChatroom.bio.thread.ChatThread;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class ChatServer {
    // 保存当前聊天中的所有Map<username,Socket>
    public static Map<String, Socket> socketMap = new HashMap<>();

    public static void main(String[] args) {
        int port = 9999;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("聊天服务器已经启动");
            while (true) {
                Socket socket = serverSocket.accept();
                // 接收Client输出的username
                InputStream inputStream = socket.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String username = bufferedReader.readLine();
                System.out.println(username   "连接到聊天服务器");
                // 连接聊天服务器成功则将它的<username,Socket>放入socketMap中
                socketMap.put(username, socket);
                System.out.println(socketMap);
                // 因为可能有多个Client与ChatServer进行交互,所以一旦有Client连接成功就新创建一个线程与之交互
                new ChatThread(username,socket).start();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

4 创建客户端Client

import com.socket.socketChatroom.bio.thread.ReadThread;
import com.socket.socketChatroom.bio.thread.WriteThread;

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

public class Client {
    public static void main(String[] args) {
        // 服务端地址,端口号
        String ip = "127.0.0.1";// 本机IP地址
        int port = 6666; // 必须和LoginServer的端口一样
        try {
            Socket client = new Socket(ip, port);
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入用户名");
            String username = scanner.nextLine();
            // 将用户名输出到LoginServer
            OutputStream outputStream = client.getOutputStream();
            PrintStream printStream = new PrintStream(outputStream);
            printStream.println(username);
            printStream.flush();
            // 接收LoginServer输出的是否登录成功标志("true"或"false")
            InputStream inputStream = client.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String state = bufferedReader.readLine();
            // 如果为"true",则为登录成功,可以开始聊天
            if (Boolean.parseBoolean(state)) {
                chat(username);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void chat(String username) {
        try {
            String ip = "127.0.0.1";// 本机IP地址
            int port = 9999;// 必须和ChatServer的端口一样
            // 连接聊天服务器ChatServer
            Socket socket = new Socket(ip, port);
            // 将username输出到ChatServer
            OutputStream outputStream = socket.getOutputStream();
            PrintStream printStream = new PrintStream(outputStream);
            printStream.println(username);
            printStream.flush();
            // 因为聊天的收发消息不一定是与同一个人,所以创建两个线程分别用于收和发
            new ReadThread(socket).start();
            new WriteThread(socket).start();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

5 创建服务器用于处理聊天的线程类ChatThread

import com.socket.socketChatroom.bio.server.ChatServer;

import java.io.*;
import java.net.Socket;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class ChatThread extends Thread {
    private final String username;
    private final Socket socket;

    public ChatThread(String username, Socket socket) {
        this.username = username;
        this.socket = socket;
    }

    @Override
    public void run() {
        while (true) {
            try {
                // 接收Client的WriteThread线程输出的消息
                InputStream inputStream = socket.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String message = bufferedReader.readLine();
                System.out.println(username   "说: "   message);
                // 将当前所有在线的Client的username存入usernameSet中
                Map<String, Socket> socketMap = ChatServer.socketMap;
                Set<String> usernameSet = new HashSet<>();
                for (Map.Entry<String, Socket> map : socketMap.entrySet()) {
                    usernameSet.add(map.getKey());
                }
                // 以"-"作为标识符,判断是群聊还是单聊
                String[] values = message.split("-");
                if (values.length == 2 && usernameSet.contains(values[0])) { //单聊
                    // values[0]为要指定发送的Client的username
                    OutputStream outputStream = socketMap.get(values[0]).getOutputStream();
                    PrintStream printStream = new PrintStream(outputStream);
                    // values[1]为消息内容
                    printStream.println(username   "说: "   values[1]);
                    printStream.flush();
                } else {//群聊
                    // 将消息发送到除自己之外的所有Client
                    for (String username : usernameSet) {
                        if (socket != socketMap.get(username)) {
                            OutputStream outputStream = socketMap.get(username).getOutputStream();
                            PrintStream printStream = new PrintStream(outputStream);
                            printStream.println(this.username   "说: "   message);
                            printStream.flush();
                        }
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

6 创建客户端Client用于发送消息的线程类WriteThread

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

public class WriteThread extends Thread {
    private final Socket socket;

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

    @Override
    public void run() {
        while (true) {
            try {
                // 获取输出流
                OutputStream outputStream = socket.getOutputStream();
                PrintStream printStream = new PrintStream(outputStream);
                // 键盘输入要发送的消息,若为单聊,则以要发送的Client的username "-",开头,比如"111-hello",表示向111这个Client发送"hello"
                Scanner scanner = new Scanner(System.in);
                System.out.println("请输入聊天内容: ");
                String message = scanner.nextLine();
                // 输出消息到ChatServer
                printStream.println(message);
                printStream.flush();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

7 创建客户端Client用于接收消息的线程类ReadThread

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;

public class ReadThread extends Thread {
    private final Socket socket;

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

    @Override
    public void run() {
        while (true) {
            try {
                // 从ChatServer获取消息
                InputStream inputStream = socket.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String message = bufferedReader.readLine();
                System.out.println(message);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

项目结构如下图

8 测试

先运行LoginServer和ChatServer,再运行多个Client
设置IDEA允许运行多个实例

8.1 登录

8.2 群聊

8.3 单聊

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持Devmax。

Java Socket实现聊天室功能的更多相关文章

  1. html5 http的轮询和Websocket原理

    这篇文章主要介绍了html5 http的轮询和Websocket原理的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. ios – Swift:使用GCDAsyncUdpSocket接收UDP

    开始:接收:发送:编辑:添加了忘记的代码行.解决方法我终于得到它使用这个套接字设置:

  3. Swift Socket 实例 两份资料不错

    Swift-使用vaporsocks库进行socket通信(基于TCP、UDP协议)http://www.hangge.com/blog/cache/detail_1588.htmlSwift-使用socket进行通信(附聊天室样例)http://www.hangge.com/blog/cache/detail_756.htmlIBM-Swift/BlueSockethttps://github.

  4. Android从服务器套接字侦听消息

    解决方法您可以在服务中创建一个线程来监听服务器.第二个线程用于发送命令.然后,对于您的服务,您应该创建一个带有处理程序的主线程.此处理程序将处理来自这两个线程的消息.

  5. Android BluetoothSocket.isConnected始终返回false

    解决方法我相信jkane001已经解决了他的问题,所以我希望这个答案可以帮助别人.首先在套接字创建之后你应该通过初始连接之后,您将能够使用socket.isConnected()检查连接状态由于connect()方法没有阻塞,所以socket之后可能还没有连接.我建议使用这样的东西顺便说一句,我发现在一些Android设备上isConnected()总是返回false.在这种情况下,只是尝试写一些东西到socket并检查是否没有异常.

  6. Android:流式摄像机数据并将其写入服务器

    我测试看它是否真的捕获了视频输出:这是以下用于设置mediaRecorder的Android代码解决方法有一些开源项目可以解决这个问题,例如Spydroid和AndroidIPCamera.你的实现类似于Spydroid,所以也许你可以调整它的一些代码.中心问题是MediaRecorder正在将原始视频帧写入套接字.它需要等到视频完成才能写入标题,但它们需要出现在文件的开头.由于套接字不可搜索,因此无法在正确的位置写入标头.上面链接的项目通过将流打包成RTSP或将一系列静态图像“流式传输”到浏览器来解决这

  7. Android应用程序:SocketException权限被拒绝(没有这样的文件或目录)

    我试图使用Fedor在这个帖子中发布的代码和上传的代码LazyloadofimagesinListView(源码:http://open-pim.com/tmp/LazyList.zip)Fedor的项目运行良好,但是当我尝试将代码调整到我的项目时,由于我碰到了这个异常(SocketException),所以事情运行得不好.不知何故,即使在清单中设置权限以获得Internet权限之后,我仍然继续获

  8. 如何从蓝牙条码扫描器读取数据符号CS3070到Android设备

    在我的项目中,我必须使用条形码扫描器SymbolCS3070通过蓝牙阅读条形码.即;我必须通过蓝牙建立Android设备和条码扫描器之间的连接.任何人都可以告诉我如何从条形码阅读器读取值,以及如何设置通信?>>首先,您必须扫描手册中的“串行端口配置文件”中的条形码.这是我工作代码的不完整版本,但你应该得到要点.我希望这个解决方案也适合你!

  9. Android TCP连接最佳做法

    我正在处理一个需要TCP连接到TCP服务器的Android应用程序我的AndroidTCP客户端正在工作可以来回发送消息.我的奇怪问题是:>在Android中处理与服务器的TCP连接的最佳方式是什么?>如何维护连接正确关闭连接)?

  10. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部