基于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的多功能聊天室 其实这个项目在我电脑已经躺了多时,最初写完项目规划后,我就认认真真地去实现了它,后来拿着这个项目区参加了面试,同样面试官也拿这个项目来 ...
随机推荐
- RSA非对称加密算法实现:Golang
RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.当时他们三人都在麻省理工学院工作.RSA ...
- 使用docker-compose部署Kafka集群
之前写过Kafka集群的部署,不过那是基于宿主机的,地址:Kafka基础教程(二):Kafka安装 和Zookeeper一样,有时想简单的连接Kafka用一下,那就需要开好几台虚拟机,如果Zookee ...
- PHP json_encode() 序列化对象、数组、空对象、空数组
$result = [ "object" => ["a" => 1], "array" => [1,2,3,4,5], & ...
- spring boot -- 配置文件application.properties 换成 application.yml
1.前言 其实两种配置文件在spring boot 的作用一样,只是写法不同 ,yml 可以写的内容更少 ,以树结构 书写内容,看起来很清晰, 但是 如果 项目配置文件设置为 既有properties ...
- 07.python函数作用域global、nonlocal、LEGB
函数作用域 作用域 一个标识符的课件范围,这就是标识符的作用域,一般常说的是变量的作用域 def foo(): x = 100 print(x) # 可以访问到吗 上例中x不可以访问到,会抛出异 ...
- 【Java常用类】Math
Math 说明 java.lang.Math提供了一系列静态方法用于科学计算.其方法的参数和返回 值类型一般为double型. 方法 abs 绝对值 acos,asin,atan,cos,sin,ta ...
- linux下编译支持opencl的opencv for android
主要的步骤其他人已经写过,请参考这篇:https://www.cnblogs.com/hrlnw/p/4720977.html 操作的细节请参考附件的pdf: https://files.cnblo ...
- 树形dp空间优化(dfn)
树形dp空间优化 介绍 有时题目会告诉我们n叉树的最大层数,或者给出一个完全n叉树树,直接做树形dp会爆空间时,就可以用这个优化方法. 多数树形dp都是先dfs到子树,再合并到根上,显然当合并到根上时 ...
- Git使用简单教程,从建库到远程操作
本地库初始化 找到项目文件->右键git bash->git init 设置签名 形式: 用户名 邮箱地址 作用: 区分不同开发人员身份 注意:这里设置的签名和登录的远程库的账号密码没有任 ...
- 基于 SSR 的预渲染首屏直出方案
基于 SSR 的预渲染首屏直出方案 Create React Doc 是一个使用 React 的 markdown 文档站点生成工具.此前在 Create React Doc 中引入了预渲染技术来预先 ...