基于Socket实现多人聊天室
当前支持:
1.仅文字
2.加入聊天室提醒
3.退出聊天室提醒
可能出现的BUG:
1.可能出现客户端发送信息后不能及时推送,需要下一个客户端发送信息后一起推送
服务端代码:

1 package com.example.demo.socket;
2
3 import org.springframework.util.ObjectUtils;
4
5 import java.io.DataInputStream;
6 import java.io.DataOutputStream;
7 import java.io.IOException;
8 import java.net.ServerSocket;
9 import java.net.Socket;
10 import java.util.HashMap;
11 import java.util.Map;
12 import java.util.concurrent.*;
13
14 public class Server {
15 public static void main(String[] args) {
16 //信息队
17 ConcurrentLinkedQueue str = new ConcurrentLinkedQueue<>();
18 //连接对,暂未使用
19 ConcurrentLinkedQueue<Map> socket = new ConcurrentLinkedQueue<>();
20 //信息接收队
21 ConcurrentLinkedQueue<Map> ins = new ConcurrentLinkedQueue<>();
22 //信息发送队
23 ConcurrentLinkedQueue<Map> outs = new ConcurrentLinkedQueue<>();
24 //服务端端口号
25 int port = 6666;
26 try {
27 ServerSocket serverSocket = new ServerSocket(port);
28 //读取信息
29 new Thread(new Runnable() {
30 @Override
31 public void run() {
32 // 参数 4 可以根据实际服务器cup设置 一般IO密集型设置为 CUP+1
33 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
34 while (true) {
35 if(!ObjectUtils.isEmpty(ins.peek())) {
36 Map in = ins.poll();
37 //延迟10毫秒执行,执行周期为 实际线程执行时间+10毫秒
38 ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
39 @Override
40 public void run() {
41 try {
42 in.put("str", ((DataInputStream) in.get("in")).readUTF());
43 str.add(in);
44 } catch (IOException e) {
45 ((ScheduledFuture)in.get("future")).cancel(true);
46 }
47 }
48 }, 10, 10, TimeUnit.MICROSECONDS);
49 in.put("future",scheduledFuture);
50 }
51 }
52 }
53 }).start();
54 //发送信息
55 new Thread(new Runnable() {
56 @Override
57 public void run() {
58 while (true) {
59 if(!ObjectUtils.isEmpty(str.peek())) {
60 Map o = (Map) str.poll();
61 for(Map m : outs) {
62 if(!o.get("client").equals(m.get("client"))) {
63 try {
64 ((DataOutputStream)m.get("out")).writeUTF( o.get("client")+":"+o.get("str"));
65 } catch (IOException e) {
66 //异常下线大法,并发送群体下线通知
67 System.out.printf("%s下线了!\n",m.get("client"));
68 Map sv = new HashMap<>();
69 sv.put("client","server");
70 sv.put("str",m.get("client")+"退出聊天室!");
71 str.add(sv);
72 outs.remove(m);
73 }
74 }
75 }
76 }
77 }
78 }
79 }).start();
80 //循环获取客户端连接
81 while (true) {
82 Socket server = serverSocket.accept();
83 Map m = new HashMap<>();
84 m.put("socket",socket);
85 m.put("in",new DataInputStream(server.getInputStream()));
86 m.put("out",new DataOutputStream(server.getOutputStream()));
87
88 //向客户端发送聊天室名,并获取客户端连接名
89 ((DataOutputStream)m.get("out")).writeUTF("6666");
90 m.put("client",((DataInputStream)m.get("in")).readUTF());
91 System.out.printf("新人%s加入聊天室!\n",m.get("client"));
92
93 ins.add(m);
94 outs.add(m);
95 socket.add(m);
96
97 //发送群体上线通知
98 Map sv = new HashMap<>();
99 sv.put("client","server");
100 sv.put("str",m.get("client")+"加入聊天室!");
101 str.add(sv);
102 }
103 } catch (Exception e) {
104 e.printStackTrace();
105 }
106 }
107 }
Server
客户端代码:

1 package com.example.demo.socket;
2
3 import java.io.DataInputStream;
4 import java.io.DataOutputStream;
5 import java.io.IOException;
6 import java.net.Socket;
7 import java.util.Scanner;
8
9 public class Client {
10
11 public static void main(String[] args) {
12 //服务端 IP
13 String serverName = "localhost";
14 //服务端 端口号
15 int port = 6666;
16 try {
17 Socket client = new Socket(serverName,port);
18 DataInputStream in = new DataInputStream(client.getInputStream());
19 DataOutputStream out = new DataOutputStream(client.getOutputStream());
20 //向服务端发送连接名,并确认服务端收到连接名且返回聊天室名
21 out.writeUTF("client");
22 out.flush();
23 System.out.printf("进入聊天室 %s \n",in.readUTF());
24 try {
25 new Thread(new Runnable() {
26 @Override
27 public void run() {
28 try {
29 while (true) {
30 System.out.println(in.readUTF());
31 }
32 } catch (IOException e) {
33 e.printStackTrace();
34 }
35 }
36 }).start();
37 while (true) {
38 out.writeUTF(new Scanner(System.in).nextLine());
39 out.flush();
40 }
41 } finally {
42 client.close();
43 }
44 } catch (Exception e) {
45 e.printStackTrace();
46 }
47
48 }
49 }
Client
基于Socket实现多人聊天室的更多相关文章
- java socket之多人聊天室Demo
一.功能介绍 该功能实现了一个类似QQ的最简单多人聊天室,如下图所示. 二.目录结构 三.服务端 1)SocketServer类,该类是服务端的主类,主要负责创建聊天窗口,创建监听客户端的线程: pa ...
- 多线程+socket实现多人聊天室
最近在学习多线程的时候打算做一个简单的多线程socke聊天的程序,结果发现网上的代码都没有完整的实现功能,所以自己实现了一个demo: demo功能大致就是,有一个服务端负责信息转发,多个客户端发送消 ...
- 基于swoole实现多人聊天室
核心的swoole代码 基本的cs(client-sercer)结构不变,这里利用的是redis的哈希和set来储存和分组;从而达到了分组,统计,定时推送等功能;最后利用onclose事件来剔除断开的 ...
- 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室
原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...
- 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室
原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...
- 基于tcp和多线程的多人聊天室-C语言
之前在学习关于网络tcp和多线程的编程,学了知识以后不用一下总绝对心虚,于是就编写了一个基于tcp和多线程的多人聊天室. 具体的实现过程: 服务器端:绑定socket对象->设置监听数-> ...
- 多人聊天室(Java)
第1部分 TCP和UDP TCP:是一种可靠地传输协议,是把消息按一个个小包传递并确认消息接收成功和正确才发送下一个包,速度相对于UDP慢,但是信息准确安全:常用于一般不要求速度和需要准确发送消息的场 ...
- Apache MiNa 实现多人聊天室
Apache MiNa 实现多人聊天室 开发环境: System:Windows JavaSDK:1.6 IDE:eclipse.MyEclipse 6.6 开发依赖库: Jdk1.4+.mina-c ...
- 基于LINUX的多功能聊天室
原文:基于LINUX的多功能聊天室 基于LINUX的多功能聊天室 其实这个项目在我电脑已经躺了多时,最初写完项目规划后,我就认认真真地去实现了它,后来拿着这个项目区参加了面试,同样面试官也拿这个项目来 ...
随机推荐
- WPF使用MVVM(一)-属性绑定
WPF使用MVVM(一)-属性绑定 简单介绍MVVM MVVM是Model(数据类型),View(界面),ViewModel(数据与界面之间的桥梁)的缩写,是一种编程模式,优点一劳永逸,初步增加一些逻 ...
- .NET 云原生架构师训练营(组合模式)--学习笔记
目录 引入 组合模式 源码 引入 在上一篇执行 _connectionDelegate 之后,HttpConnectionMiddleware 处理请求 return connection.Proce ...
- Nginx日志配置及日志分析脚本案例
https://blog.csdn.net/bbwangj/article/details/82186162 nginx的log日志分为access log 和 error log 其中access ...
- spring security 自动登录 --- 心得
1.前言 仍然是使用cookie存储登录数据,但是存储的数据 由 spring security自动创建 ,当登出后自动删除cookie, 如果不登出也仍在生命周期内,关闭浏览器再打开将会自动登录,无 ...
- [未完] Linux 4.4 USB —— spiflash模拟usb大容量存储设备 调试记录 Gadget Mass Stroage
linux 4.4 USB Gadget Mass Stroage 硬件平台: licheepi nano衍生 调试记录 驱动信息 │ This driver is a replacement for ...
- Keepalived高可用、四层负载均衡
目录 Keepalived高可用 高可用简介 常用的工具 问题 名称解释 VRRP协议 部署keepalived 下载安装 Keepalived配置 保证nginx配置一样 解决keepalived的 ...
- 2022GDUT寒训专题一I题
题目 题面 给一个长度为 N的数组,一个长为 K的滑动窗体从最左端移至最右端,你只能看到窗口中的 K 个数,每次窗体向右移动一位,如下图: 窗口位置 最小值 最大值 [1 3 -1] -3 5 3 6 ...
- 学习鸟哥linux私房菜--安装centos5.6(u盘安装,中文乱码)
题头为"学习鸟哥Linux私房菜"的内容,均为博主在看鸟哥的Linux私房菜第三版的学习经历收获.以下正文: 鸟哥第一部分讲Linux规则与安装,看到第四章正式开始讲实际安装,于是 ...
- vue学习7-v-show和v-if
1. v-show:这个是一次性会把所有的都渲染出来,然后通过简单的切换display值来修改是否需要被渲染.所以在需要频繁切换的情况下推荐使用.v-show不能在template标签上使用. 2. ...
- gin访问和使用数据库
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysq ...