基于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的多功能聊天室 其实这个项目在我电脑已经躺了多时,最初写完项目规划后,我就认认真真地去实现了它,后来拿着这个项目区参加了面试,同样面试官也拿这个项目来 ...
随机推荐
- UTF-8,GBK,ANSI之间的关系和区别
GBK应该是属于ANSI之中的,在ANSI的国际通用集,GBK是专门来解决中文编码的,是双字节的,不论中英文都是双字节,而UTF-8是才用的另外的一种编码方式,对英文是用8位,对中文使用24位,是和A ...
- Swoole 中使用 Context 类管理上下文,防止发生数据错乱
前面的文章中,我们说过:不能使用类静态变量 Class::$array / 全局变量 global $_array / 全局对象属性 $object->array / 其他超全局变量 $GLOB ...
- 在安装pdfplumber时报错 Microsoft Visual C++ 14.0 is required.
在安装pdfplumber时报下列错误: 解决方法: 更新pip ,因为pip 版本太旧 来自为知笔记(Wiz)
- POJ 1664 放苹果 (递推思想)
原题链接:http://poj.org/problem?id=1664 思路:苹果m个,盘子n个.假设 f ( m , n ) 代表 m 个苹果,n个盘子有 f ( m , n ) 种放法. 根据 n ...
- 大数据安全与RANGER学习和使用
概述 再说ranger之前需要明白一下大数据的安全体系的整体介绍,安全体系其实也就是权限可控,先说说权限:权限管理的目标,绝对不是简单的在技术层面建立起用户,密码和权限点的映射关系这么简单的事,更重要 ...
- netty系列之:一口多用,使用同一端口运行不同协议
目录 简介 SocksPortUnificationServerHandler 自定义PortUnificationServerHandler 总结 简介 在之前的文章中,我们介绍了在同一个netty ...
- Linux环境下的Docker的安装和部署、学习二
DockerFile体系结构(保留字指令) FROM:基础镜像,当前新镜像是基于哪个镜像的 MAINTAINER:镜像维护者的姓名和邮箱地址 RUN:容器构建时需要运行的命令 EXPOSE:当前容器对 ...
- 动态代理及java演示
代理模式的理解 首先代理二字的含义,程序中代理与字面意思的代理并无区别.比如现实生活中办理车辆审车,我们经常会听说花钱找代理(又称黄牛)办手续,即办手续这个事,不是我们亲自执行,而是通过代理( ...
- 《剑指offer》面试题32 - III. 从上到下打印二叉树 III
问题描述 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推. 例如: 给定二叉树: [3,9,20, ...
- Linuxqq shell脚本安装后的卸载
官方下载和帮助页面: 传送门 linuxqq_2.0.0-b1 的时候,并没有发布 MIPS64 的 DEB 包,只能用 .sh 安装,需要手动删除卸载.愚人节发布的 beta2 新增了 MIPS64 ...