基于websocket和java的多人聊天室
- 格式:docx
- 大小:28.80 KB
- 文档页数:8
⽤javaWebSocket做⼀个聊天室最近⼀个项⽬中,需要⽤到Java的websocket新特性,于是就学了⼀下,感觉这技术还挺好玩的,瞬间知道⽹页上⾯的那些在线客服是怎么做的了。
先看图:实现了多客户机进⾏实时通讯。
下⾯看代码项⽬结构图:很简单,就1个类,1个页⾯然后看具体代码先看后端代码package com.main;import java.io.IOException;import java.util.concurrent.CopyOnWriteArraySet;import javax.websocket.*;import javax.websocket.server.ServerEndpoint;/*** @ServerEndpoint 注解是⼀个类层次的注解,它的功能主要是将⽬前的类定义成⼀个websocket服务器端,* 注解的值将被⽤于监听⽤户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端*/@ServerEndpoint("/websocket")public class H5ServletServerSocket {// 静态变量,⽤来记录当前在线连接数。
应该把它设计成线程安全的。
private static int onlineCount = 0;// concurrent包的线程安全Set,⽤来存放每个客户端对应的MyWebSocket对象。
若要实现服务端与单⼀客户端通信的话,可以使⽤Map来存放,其中Key可以为⽤户标识 private static CopyOnWriteArraySet<H5ServletServerSocket> webSocketSet = new CopyOnWriteArraySet<H5ServletServerSocket>();// 与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;/*** 连接建⽴成功调⽤的⽅法** @param session* 可选的参数。
基于websocket的聊天系统设计与实现WebSocket是一种在Web浏览器和服务器之间进行全双工通信的通信协议。
它允许客户端和服务器之间实时地进行双向通信,而不需要客户端发起请求。
基于WebSocket的聊天系统是一个能够实现实时通信的应用程序,用户可以通过该应用程序在一个或多个聊天室中发送消息、接收消息,并与其他用户进行实时交流。
设计和实现一个基于WebSocket的聊天系统需要考虑以下几个方面:1. 前后端交互设计:前端通过WebSocket与后端建立连接,后端负责处理接收到的消息并转发给目标用户或聊天室。
前端需要实现用户注册、登录、发送消息、接收消息等功能。
后端需要实现身份验证、消息路由和转发等功能。
2. 用户认证和身份验证:聊天系统需要确保只有经过身份验证的用户才能进入聊天室。
可以使用JWT(JSON Web Token)或其他身份验证机制来验证用户的身份,并在每个WebSocket连接上进行验证。
3. 消息的发送和接收:用户可以通过界面输入消息并将其发送到聊天室或特定的用户。
接收消息时,前端应能够实时地接收到其他用户发送的消息,并将其显示在用户界面上。
后端需要将接收到的消息转发给相应的聊天室或用户。
4. 聊天室管理:聊天系统中可以有多个聊天室,用户可以选择进入或创建聊天室。
后端需要提供API,用于创建聊天室、查找聊天室、加入聊天室和离开聊天室等功能。
5. 消息存储和历史记录:可以考虑将用户发送的消息存储在数据库中,以便后续查询和展示历史记录。
后端需要设计相应的数据库表结构,并提供API用于存储和查询消息。
6. 安全性和性能优化:聊天系统需要考虑安全性,并采取必要的措施防止恶意攻击和数据泄露。
同时,为了提高系统的性能,可以使用消息队列或缓存技术来处理用户的消息请求。
基于以上需求,设计和实现一个基于WebSocket的聊天系统可以按如下步骤进行:1. 前端页面设计与开发:设计用户界面,包括用户注册、登录、聊天室列表、聊天室界面等。
Java WebSocket案例:聊天室应用背景WebSocket是一种在Web浏览器和服务器之间进行双向通信的技术标准。
相比传统的HTTP请求-响应模式,WebSocket允许服务器主动向客户端推送消息,实现了实时通信的能力。
在Java中,我们可以使用Java API for WebSocket(JSR 356)来开发WebSocket应用。
本案例将展示如何使用Java WebSocket API来构建一个简单的聊天室应用。
在这个聊天室中,多个用户可以同时加入并实时发送消息,所有用户都能看到其他用户发送的消息。
过程1. 创建WebSocket服务器首先,我们需要创建一个WebSocket服务器来处理客户端的连接和消息。
在Java 中,可以使用javax.websocket包中的注解和接口来实现WebSocket服务器。
import java.io.IOException;import java.util.Collections;import java.util.HashSet;import java.util.Set;import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;@ServerEndpoint("/chat")public class ChatServer {private static Set<Session> sessions = Collections.synchronizedSet(new Has hSet<>());@OnOpenpublic void onOpen(Session session) {sessions.add(session);}@OnMessagepublic void onMessage(String message, Session session) throws IOException{for (Session s : sessions) {s.getBasicRemote().sendText(message);}}@OnClosepublic void onClose(Session session) {sessions.remove(session);}@OnErrorpublic void onError(Session session, Throwable error) {System.err.println("发生错误:" + error.getMessage());}}在上述代码中,我们使用@ServerEndpoint注解来指定WebSocket服务器的URL路径。
Java Socket实现多人聊天室---swing做UI标签:socket聊天javaexception服务器string2011-08-31 15:06 20679人阅读评论(25) 收藏举报分类:java(21)版权声明:本文为博主原创文章,未经博主允许不得转载。
今天翻硬盘的workspace发现一个Java Socket实现多人聊天室的源码,不记得是什么时候的事情了,貌似不是我写的。
但写得还不错,至少算个有模有样的聊天室工具。
我简单的修改了一下,拿出来跟大家分享一下,仅供参考。
界面是用swing写的,还不懒,简约大方。
有图有真相:正如上图所示,这个程序分为服务器端和客户端,说白了就是两个main class,用eclipse 直接运行之。
聊天室的设计思想是:在局域网下,利用socket进行连接通信,当服务器端启动的时候,利用Thread线程不停的等待客户端的链接;当有客户端开启连接的时候,服务器端通过IO流反馈“上线用户”信息给客户端,客户端也使用线程不停的接收服务器的信息,从而实现多人在线聊天功能。
程序中有三个类,分别Server.java(服务器端)、Client(客户端)、User.java(javabean)。
代码如下:Server.java(服务器端):[html]view plaincopy1.import java.awt.BorderLayout;2.import java.awt.Color;3.import java.awt.GridLayout;4.import java.awt.Toolkit;5.import java.awt.event.ActionEvent;6.import java.awt.event.ActionListener;7.import java.awt.event.WindowAdapter;8.import java.awt.event.WindowEvent;9.import java.io.BufferedReader;10.i mport java.io.IOException;11.i mport java.io.InputStreamReader;12.i mport java.io.PrintWriter;13.i mport .BindException;14.i mport .ServerSocket;15.i mport .Socket;16.i mport java.util.ArrayList;17.i mport java.util.StringTokenizer;18.19.i mport javax.swing.DefaultListModel;20.i mport javax.swing.JButton;21.i mport javax.swing.JFrame;22.i mport javax.swing.JLabel;23.i mport javax.swing.JList;24.i mport javax.swing.JOptionPane;25.i mport javax.swing.JPanel;26.i mport javax.swing.JScrollPane;27.i mport javax.swing.JSplitPane;28.i mport javax.swing.JTextArea;29.i mport javax.swing.JTextField;30.i mport javax.swing.border.TitledBorder;31.32.p ublic class Server {33.34. private JFrame frame;35. private JTextArea contentArea;36. private JTextField txt_message;37. private JTextField txt_max;38. private JTextField txt_port;39. private JButton btn_start;40. private JButton btn_stop;41. private JButton btn_send;42. private JPanel northPanel;43. private JPanel southPanel;44. private JScrollPane rightPanel;45. private JScrollPane leftPanel;46. private JSplitPane centerSplit;47. private JList userList;48. private DefaultListModel listModel;49.50. private ServerSocket serverSocket;51. private ServerThread serverThread;52. private ArrayList<ClientThread> clients;53.54. private boolean isStart = false;55.56. // 主方法,程序执行入口57. public static void main(String[] args) {58. new Server();59. }60.61. // 执行消息发送62. public void send() {63. if (!isStart) {64. JOptionPane.showMessageDialog(frame, "服务器还未启动,不能发送消息!", "错误",65. JOptionPane.ERROR_MESSAGE);66. return;67. }68. if (clients.size() == 0) {69. JOptionPane.showMessageDialog(frame, "没有用户在线,不能发送消息!", "错误",70. JOptionPane.ERROR_MESSAGE);71. return;72. }73. String message = txt_message.getText().trim();74. if (message == null || message.equals("")) {75. JOptionPane.showMessageDialog(frame, "消息不能为空!", "错误",76. JOptionPane.ERROR_MESSAGE);77. return;78. }79. sendServerMessage(message);// 群发服务器消息80. contentArea.append("服务器说:" + txt_message.getText() + "\r\n");81. txt_message.setText(null);82. }83.84. // 构造放法85. public Server() {86.frame = new JFrame("服务器");87. // 更改JFrame的图标:88. //frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Client.class.getResource("qq.png")));89. frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Server.class.getResource("qq.png")));90.contentArea = new JTextArea();91. contentArea.setEditable(false);92. contentArea.setForeground(Color.blue);93.txt_message = new JTextField();94.txt_max = new JTextField("30");95.txt_port = new JTextField("6666");96.btn_start = new JButton("启动");97.btn_stop = new JButton("停止");98.btn_send = new JButton("发送");99. btn_stop.setEnabled(false);100.listModel = new DefaultListModel();erList = new JList(listModel);102.103.southPanel = new JPanel(new BorderLayout()); 104. southPanel.setBorder(new TitledBorder("写消息")); 105. southPanel.add(txt_message, "Center");106. southPanel.add(btn_send, "East");107.leftPanel = new JScrollPane(userList);108. leftPanel.setBorder(new TitledBorder("在线用户"));109.110.rightPanel = new JScrollPane(contentArea);111. rightPanel.setBorder(new TitledBorder("消息显示区"));112.113.centerSplit = new JSplitPane(JSplitPane.HORIZONTAL _SPLIT, leftPanel,114. rightPanel);115. centerSplit.setDividerLocation(100);116.northPanel = new JPanel();117. northPanel.setLayout(new GridLayout(1, 6)); 118. northPanel.add(new JLabel("人数上限"));119. northPanel.add(txt_max);120. northPanel.add(new JLabel("端口"));121. northPanel.add(txt_port);122. northPanel.add(btn_start);123. northPanel.add(btn_stop);124. northPanel.setBorder(new TitledBorder("配置信息"));125.126. frame.setLayout(new BorderLayout());127. frame.add(northPanel, "North");128. frame.add(centerSplit, "Center");129. frame.add(southPanel, "South");130. frame.setSize(600, 400);131. //frame.setSize(Toolkit.getDefaultToolkit().getScr eenSize());//设置全屏132. int screen_width = Toolkit.getDefaultToolkit().get ScreenSize().width;133. int screen_height = Toolkit.getDefaultToolkit().ge tScreenSize().height;134. frame.setLocation((screen_width - frame.getWidth() ) / 2,135. (screen_height - frame.getHeight()) / 2);136. frame.setVisible(true);137.138. // 关闭窗口时事件139. frame.addWindowListener(new WindowAdapter() { 140. public void windowClosing(WindowEvent e) { 141. if (isStart) {142. closeServer();// 关闭服务器143. }144. System.exit(0);// 退出程序145. }146. });147.148. // 文本框按回车键时事件149. txt_message.addActionListener(new ActionListener() {150. public void actionPerformed(ActionEvent e) { 151. send();152. }153. });154.155. // 单击发送按钮时事件156. btn_send.addActionListener(new ActionListener() {157. public void actionPerformed(ActionEvent arg0) {158. send();159. }160. });161.162. // 单击启动服务器按钮时事件163. btn_start.addActionListener(new ActionListener() {164. public void actionPerformed(ActionEvent e) { 165. if (isStart) {166. JOptionPane.showMessageDialog(frame, "服务器已处于启动状态,不要重复启动!",167. "错误", JOptionPane.ERROR_MESSAGE);168. return;169. }170. int max;171. int port;172. try {173. try {174.max = Integer.parseInt(txt_max.get Text());175. } catch (Exception e1) {176. throw new Exception("人数上限为正整数!");177. }178. if (max <= 0) {179. throw new Exception("人数上限为正整数!");180. }181. try {182.port = Integer.parseInt(txt_port.g etText());183. } catch (Exception e1) {184. throw new Exception("端口号为正整数!");185. }186. if (port <= 0) {187. throw new Exception("端口号为正整数!");188. }189. serverStart(max, port);190. contentArea.append("服务器已成功启动!人数上限:" + max + ",端口:" + port191. + "\r\n");192. JOptionPane.showMessageDialog(frame, "服务器成功启动!");193. btn_start.setEnabled(false);194. txt_max.setEnabled(false);195. txt_port.setEnabled(false);196. btn_stop.setEnabled(true);197. } catch (Exception exc) {198. JOptionPane.showMessageDialog(frame, e xc.getMessage(),199. "错误", JOptionPane.ERROR_MESSAGE);200. }201. }202. });203.204. // 单击停止服务器按钮时事件205. btn_stop.addActionListener(new ActionListener() {206. public void actionPerformed(ActionEvent e) { 207. if (!isStart) {208. JOptionPane.showMessageDialog(frame, "服务器还未启动,无需停止!", "错误",209. JOptionPane.ERROR_MESSAGE); 210. return;211. }212. try {213. closeServer();214. btn_start.setEnabled(true);215. txt_max.setEnabled(true);216. txt_port.setEnabled(true);217. btn_stop.setEnabled(false);218. contentArea.append("服务器成功停止!\r\n");219. JOptionPane.showMessageDialog(frame, "服务器成功停止!");220. } catch (Exception exc) {221. JOptionPane.showMessageDialog(frame, "停止服务器发生异常!", "错误",222. JOptionPane.ERROR_MESSAGE); 223. }224. }225. });226. }227.228. // 启动服务器229. public void serverStart(int max, int port) throws java .net.BindException {230. try {231.clients = new ArrayList<ClientThread>();232.serverSocket = new ServerSocket(port); 233.serverThread = new ServerThread(serverSocket, max);234. serverThread.start();235.isStart = true;236. } catch (BindException e) {237.isStart = false;238. throw new BindException("端口号已被占用,请换一个!");239. } catch (Exception e1) {240. e1.printStackTrace();241.isStart = false;242. throw new BindException("启动服务器异常!"); 243. }244. }245.246. // 关闭服务器247. @SuppressWarnings("deprecation")248. public void closeServer() {249. try {250. if (serverThread != null)251. serverThread.stop();// 停止服务器线程252.253. for (int i = clients.size() - 1; i >= 0; i--) {254. // 给所有在线用户发送关闭命令255. clients.get(i).getWriter().println("CLOSE");256. clients.get(i).getWriter().flush(); 257. // 释放资源258. clients.get(i).stop();// 停止此条为客户端服务的线程259. clients.get(i).reader.close();260. clients.get(i).writer.close();261. clients.get(i).socket.close();262. clients.remove(i);263. }264. if (serverSocket != null) {265. serverSocket.close();// 关闭服务器端连接266. }267. listModel.removeAllElements();// 清空用户列表268.isStart = false;269. } catch (IOException e) {270. e.printStackTrace();271.isStart = true;272. }273. }274.275. // 群发服务器消息276. public void sendServerMessage(String message) { 277. for (int i = clients.size() - 1; i >= 0; i--) { 278. clients.get(i).getWriter().println("服务器:" + message + "(多人发送)");279. clients.get(i).getWriter().flush();280. }281. }282.283. // 服务器线程284. class ServerThread extends Thread {285. private ServerSocket serverSocket;286. private int max;// 人数上限287.288. // 服务器线程的构造方法289. public ServerThread(ServerSocket serverSocket, int max) {290.this.serverSocket = serverSocket;291.this.max = max;292. }293.294. public void run() {295. while (true) {// 不停的等待客户端的链接296. try {297. Socket socket = serverSocket.accept();298. if (clients.size() == max) {// 如果已达人数上限299. BufferedReader r = new BufferedRea der(300. new InputStreamReader(sock et.getInputStream()));301. PrintWriter w = new PrintWriter(so cket302. .getOutputStream()); 303. // 接收客户端的基本用户信息304. String inf = r.readLine();305. StringTokenizer st = new StringTok enizer(inf, "@");306. User user = new User(st.nextToken( ), st.nextToken());307. // 反馈连接成功信息308. w.println("MAX@服务器:对不起," + user.getName()309. + user.getIp() + ",服务器在线人数已达上限,请稍后尝试连接!");310. w.flush();311. // 释放资源312. r.close();313. w.close();314. socket.close();315. continue;316. }317. ClientThread client = new ClientThread (socket);318. client.start();// 开启对此客户端服务的线程319. clients.add(client);320. listModel.addElement(client.getUser().getName());// 更新在线列表321. contentArea.append(client.getUser().ge tName()322. + client.getUser().getIp() + "上线!\r\n");323. } catch (IOException e) {324. e.printStackTrace();325. }326. }327. }328. }329.330. // 为一个客户端服务的线程331. class ClientThread extends Thread {332. private Socket socket;333. private BufferedReader reader;334. private PrintWriter writer;335. private User user;336.337. public BufferedReader getReader() {338. return reader;339. }340.341. public PrintWriter getWriter() {342. return writer;343. }344.345. public User getUser() {346. return user;347. }348.349. // 客户端线程的构造方法350. public ClientThread(Socket socket) {351. try {352.this.socket = socket;353.reader = new BufferedReader(new InputStrea mReader(socket354. .getInputStream()));355.writer = new PrintWriter(socket.getOutputS tream());356. // 接收客户端的基本用户信息357. String inf = reader.readLine();358. StringTokenizer st = new StringTokenizer(i nf, "@");er = new User(st.nextToken(), st.nextTok en());360. // 反馈连接成功信息361. writer.println(user.getName() + user.getIp () + "与服务器连接成功!");362. writer.flush();363. // 反馈当前在线用户信息364. if (clients.size() > 0) {365. String temp = "";366. for (int i = clients.size() - 1; i >= 0; i--) {367. temp += (clients.get(i).getUser().getName() + "/" + clients368. .get(i).getUser().getIp())369. + "@";370. }371. writer.println("USERLIST@" + clients.s ize() + "@" + temp);372. writer.flush();373. }374. // 向所有在线用户发送该用户上线命令375. for (int i = clients.size() - 1; i >= 0; i --) {376. clients.get(i).getWriter().println( 377. "ADD@" + user.getName() + user .getIp());378. clients.get(i).getWriter().flush(); 379. }380. } catch (IOException e) {381. e.printStackTrace();382. }383. }384.385. @SuppressWarnings("deprecation")386. public void run() {// 不断接收客户端的消息,进行处理。
JAVA结合WebSocket实现简单客服聊天功能说明:该⽰例只简单的实现了客服聊天功能。
1、聊天记录没有保存到数据库中,⼀旦服务重启,消息记录将会没有,如果需要保存到数据库中,可以扩展2、页⾯样式⽤的⽹上模板,样式可以⾃⼰进⾏修改3、只能由⽤户主要发起会话,管理员⽆法主动进⾏对话4、页⾯之间跳转代码没有包含在⾥⾯,请⾃⼰书写,在管理员消息列表页中,需要把该咨询的⽤户ID带到客服回复页⾯中5、${websocket_url} 这个为项⽬的URL地址效果截图:客服回复页⾯(member_admin_chat.html)管理员消息列表页(member_admin_chat_list.html)⽤户咨询页⾯(member_chat.html)代码:页⾯所需要⽤到的基础样式、图⽚,下载链接:(这个只是⾃⼰⽹上下载的样式demo,可以根据⾃⼰的来)pom.xml <dependency><groupId>javax</groupId><artifactId>javaee-api</artifactId><version>8.0</version><scope>provided</scope></dependency>或者jar包javax.websocket-api-1.0.jar下载地址:配置类WebSocketConfig.javapackage com.config;import javax.websocket.Endpoint;import javax.websocket.server.ServerApplicationConfig;import javax.websocket.server.ServerEndpointConfig;import java.util.Set;public class WebSocketConfig implements ServerApplicationConfig {@Overridepublic Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> endpointClasses) { return null;}@Overridepublic Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {//在这⾥会把含有@ServerEndpoint注解的类扫描加载进来,可以在这⾥做过滤等操作return scanned;}}消息DTO类(使⽤了lombok,这⾥不在多做说明)ChatDTO.javapackage com.websocket.dto;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import lombok.experimental.Accessors;/*** @author 。
JavaSocket+多线程实现多⼈聊天室功能本⽂实例为⼤家分享了Java Socket+多线程实现多⼈聊天室的具体代码,供⼤家参考,具体内容如下思路简介分为客户端和服务器两个类,所有的客户端将聊的内容发送给服务器,服务器接受后,将每⼀条内容发送给每⼀个客户端,客户端再显⽰在终端上。
客户端设计客户端包含2个线程,1个⽤来接受服务器的信息,再显⽰,1个⽤来接收键盘的输⼊,发送给服务器。
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import .Socket;import java.nio.charset.StandardCharsets;import java.util.Scanner;public class WeChatClient { //WeChat的客户端类private Socket client;private String name;private InputStream in;private OutputStream out;private MassageSenter massageSenter;private MassageGeter massageGeter;class MassageGeter extends Thread{ //⼀个⼦线程类,⽤于客户端接收消息MassageGeter() throws IOException{in = client.getInputStream();}@Overridepublic void run() {int len;byte[] bytes = new byte[1024];try {while ((len = in.read(bytes)) != -1) { //此函数是阻塞的System.out.println(new String(bytes,0,len, StandardCharsets.UTF_8));}}catch (IOException e){System.out.println(e.toString());}System.out.println("Connection interruption");}}class MassageSenter extends Thread{ //⼀个⼦线程类,⽤于发送消息给服务器MassageSenter() throws IOException{out = client.getOutputStream();}@Overridepublic void run() {Scanner scanner = new Scanner(System.in);try {while (scanner.hasNextLine()) { //此函数为阻塞的函数String massage = scanner.nextLine();out.write((name + " : " + massage).getBytes(StandardCharsets.UTF_8));if(massage.equals("//exit"))break;}}catch (IOException e){e.printStackTrace();}}}WeChatClient(String name, String host, int port) throws IOException {//初始化,实例化发送和接收2个线程 = name;client = new Socket(host,port);massageGeter = new MassageGeter();massageSenter = new MassageSenter();}void login() throws IOException{//登录时,先发送名字给服务器,在接收到服务器的正确回应之后,启动线程out.write(name.getBytes(StandardCharsets.UTF_8));byte[] bytes = new byte[1024];int len;len = in.read(bytes);String answer = new String(bytes,0,len, StandardCharsets.UTF_8);if(answer.equals("logined!")) {System.out.println("Welcome to WeChat! "+name);massageSenter.start();massageGeter.start();try {massageSenter.join();//join()的作⽤是等线程结束之后再继续执⾏主线程(main)massageGeter.join();}catch (InterruptedException e){System.err.println(e.toString());}}else{System.out.println("Server Wrong");}client.close();}public static void main(String[] args) throws IOException{//程序⼊⼝String host = "127.0.0.1";WeChatClient client = new WeChatClient("Uzi",host,7777);client.login();}}服务器设计服务器包含3个线程类,端⼝监听线程,客户端接收信息线程,发送信息线程。
使⽤WebSocket实现即时通讯(⼀个群聊的聊天室)随着互联⽹的发展,传统的HTTP协议已经很难满⾜Web应⽤⽇益复杂的需求了。
近年来,随着HTML5的诞⽣,WebSocket协议被提出,它实现了浏览器与服务器的全双⼯通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。
传统的HTTP协议是⽆状态的,每次请求(request)都要由客户端(如浏览器)主动发起,服务端进⾏处理后返回response结果,⽽服务端很难主动向客户端发送数据;这种客户端是主动⽅,服务端是被动⽅的传统Web模式对于信息变化不频繁的Web应⽤来说造成的⿇烦较⼩,⽽对于涉及实时信息的Web应⽤却带来了很⼤的不便,如带有即时通信、实时数据、订阅推送等功能的应⽤。
在WebSocket规范提出之前,开发⼈员若要实现这些实时性较强的功能,经常会使⽤折衷的解决⽅法:轮询(polling)和Comet技术。
其实后者本质上也是⼀种轮询,只不过有所改进。
轮询是最原始的实现实时Web应⽤的解决⽅案。
轮询技术要求客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动。
明显地,这种⽅法会导致过多不必要的请求,浪费流量和服务器资源。
Comet技术⼜可以分为长轮询和流技术。
长轮询改进了上述的轮询技术,减⼩了⽆⽤的请求。
它会为某些数据设定过期时间,当数据过期后才会向服务端发送请求;这种机制适合数据的改动不是特别频繁的情况。
流技术通常是指客户端使⽤⼀个隐藏的窗⼝与服务端建⽴⼀个HTTP长连接,服务端会不断更新连接状态以保持HTTP长连接存活;这样的话,服务端就可以通过这条长连接主动将数据发送给客户端;流技术在⼤并发环境下,可能会考验到服务端的性能。
这两种技术都是基于请求-应答模式,都不算是真正意义上的实时技术;它们的每⼀次请求、应答,都浪费了⼀定流量在相同的头部信息上,并且开发复杂度也较⼤。
**伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能⼒。
javasocket实现聊天室java实现多⼈聊天功能⽤java socket做⼀个聊天室,实现多⼈聊天的功能。
看了极客学院的视频后跟着敲的。
(1DAY)服务端:1. 先写服务端的类MyServerSocket,⾥⾯放⼀个监听线程,⼀启动就好2. 实现服务端监听类ServerListener.java,⽤accept来监听,⼀旦有客户端连上,⽣成新的socket,就新建个线程实例ChatSocket。
启动线程后就把线程交给ChatManager管理3. 在ChatSocket中实现从客户端读取内容,把读取到的内容发给集合内所有的客户端4. ChatManager⾥⾯⽤vector来管理socket线程实例ChatSocket,并实现发送信息给其他的客户端客户端:1. 新建⼀个继承JFrame的MainWindow.java类,主要实现聊天窗⼝的UI,以及事件响应。
2. 新建StartClient.java类,把MainWindow中⽣成MainWindow主⽅法部分代码拷贝过来,这样就能在主程序中把窗体执⾏出来了。
3. 新建ChatManager(需要单例化的类)管理socket,实现聊天的输⼊输出功能。
最后记得在1中新建窗⼝后,传⼀份frame 的引⽤到ChatManager中,才能实现ChatManager对界⾯的显⽰。
⼯程结构如图以下为代码服务端:1. 先写服务端的类MyServerSocket,⾥⾯放⼀个监听线程,⼀启动就好package com.starnet.testserversocket.main;public class MyServerSocket {public static void main(String[] args) {new ServerListener().start();}}2.实现服务端监听类ServerListener.java,⽤accept来监听,⼀旦有客户端连上,⽣成新的socket,就新建个线程实例ChatSocket。
Swoole案例:基于WebSocket的多人在线聊天室1. 案例背景随着互联网的发展和智能手机的普及,实时通信变得越来越重要。
传统的HTTP协议在实现实时通信时存在一些限制,而WebSocket协议则可以提供双向通信的能力,使得实时通信更加高效和稳定。
Swoole是一个基于PHP语言开发的协程网络通信引擎,提供了丰富的网络编程组件和工具,可以方便地实现高性能的网络应用。
在本案例中,我们将使用Swoole来构建一个基于WebSocket的多人在线聊天室,实现实时的多人聊天功能。
2. 案例过程2.1 环境准备在开始之前,需要确保已经安装了PHP和Swoole扩展。
可以通过以下命令来安装Swoole扩展:$ pecl install swoole2.2 服务器端代码首先,我们需要创建一个服务器端的PHP脚本,用于接收和处理客户端的连接和消息。
在这个案例中,我们使用Swoole的WebSocket服务器类来实现服务器端的功能。
<?php// 创建WebSocket服务器$server = new Swoole\WebSocket\Server("0.0.0.0", 9501);// 监听WebSocket连接事件$server->on('open', function (Swoole\WebSocket\Server $server, $request) { echo "New connection: {$request->fd}\n";});// 监听WebSocket消息事件$server->on('message', function (Swoole\WebSocket\Server $server, $frame) { echo "Received message: {$frame->data}\n";// 广播消息给所有客户端foreach ($server->connections as $fd) {$server->push($fd, $frame->data);}});// 监听WebSocket关闭事件$server->on('close', function ($server, $fd) {echo "Connection closed: {$fd}\n";});// 启动WebSocket服务器$server->start();上述代码中,我们创建了一个WebSocket服务器,并监听了open、message和close三个事件。
最新基于websocket与java的多人聊天室实现架构html5+websocket+javaEE7+tomcat8JavaEE7 最新的websocket1.0 APITomcat8开始支持websocket1.0 API【Tomcat implements the Java WebSocket 1.0 API defined by JSR-356】在编写代码之前你要导入javaEE7的jar包以便使用websocket API,将此项目部署到tomcat8里面。
具体代码如下:Java端:ChatAnnotation类;使用的是注解的方式。
package websocket.chat;import java.io.IOException;import java.util.Set;import java.util.concurrent.CopyOnWriteArraySet;import java.util.concurrent.atomic.AtomicInteger;import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;import org.apache.juli.logging.Log;import org.apache.juli.logging.LogFactory;import util.HTMLFilter;@ServerEndpoint(value = "/websocket/chat")public class ChatAnnotation {private static final Log log =LogFactory.getLog(ChatAnnotation.class);private static final String GUEST_PREFIX = "Guest";private static final AtomicInteger connectionIds = new AtomicInteger(0);private static final Set<ChatAnnotation> connections =new CopyOnWriteArraySet<>();private final String nickname;private Session session;public ChatAnnotation() {nickname = GUEST_PREFIX + connectionIds.getAndIncrement(); }@OnOpenpublic void start(Session session) {this.session = session;connections.add(this);String message = String.format("* %s %s", nickname, "has joined.");broadcast(message);}@OnClosepublic void end() {connections.remove(this);String message = String.format("* %s %s",nickname, "has disconnected.");broadcast(message);}@OnMessagepublic void incoming(String message) {// Never trust the clientString filteredMessage = String.format("%s: %s",nickname, HTMLFilter.filter(message.toString()));broadcast(filteredMessage);}@OnErrorpublic void onError(Throwable t) throws Throwable {log.error("Chat Error: " + t.toString(), t);}private static void broadcast(String msg) {for (ChatAnnotation client : connections) {try {synchronized (client) {client.session.getBasicRemote().sendText(msg);}} catch (IOException e) {log.debug("Chat Error: Failed to send message to client", e);connections.remove(client);try {client.session.close();} catch (IOException e1) {// Ignore}String message = String.format("* %s %s",client.nickname, "has been disconnected."); broadcast(message);}}}}里面的juli.jar包可以百度一下自行下载。
util.HTMLFilter类如下:HTMLFilter类。
package util;/*** HTML filter utility.** @author Craig R. McClanahan* @author Tim Tye*/public final class HTMLFilter {/*** Filter the specified message string for characters that are sensitive* in HTML. This avoids potential attacks caused by including JavaScript* codes in the request URL that is often reported in error messages. ** @param message The message string to be filtered*/public static String filter(String message) {if (message == null)return (null);char content[] = new char[message.length()];message.getChars(0, message.length(), content, 0);StringBuilder result = new StringBuilder(content.length + 50); for (int i = 0; i < content.length; i++) {switch (content[i]) {case '<':result.append("<");break;case '>':result.append(">");break;case '&':result.append("&");break;case '"':result.append(""");break;default:result.append(content[i]);}}return (result.toString());}}接下来是web端:Chat.xhtml<?xml version="1.0" encoding="UTF-8"?><html xmlns="/1999/xhtml" xml:lang="en"><head><title>Apache Tomcat WebSocket Examples: Chat</title><style type="text/css"><![CDATA[input#chat {width: 410px}#console-container {width: 400px;}#console {border: 1px solid #CCCCCC;border-right-color: #999999;border-bottom-color: #999999;height: 170px;overflow-y: scroll;padding: 5px;width: 100%;}#console p {padding: 0;margin: 0;}]]></style><script type="application/javascript"><![CDATA["use strict";var Chat = {};Chat.socket = null;Chat.connect = (function(host) {if ('WebSocket' in window) {Chat.socket = new WebSocket(host);} else if ('MozWebSocket' in window) {Chat.socket = new MozWebSocket(host);} else {Console.log('Error: WebSocket is not supported by this browser.');return;}Chat.socket.onopen = function () {Console.log('Info: WebSocket connection opened.');document.getElementById('chat').onkeydown =function(event) {if (event.keyCode == 13) {Chat.sendMessage();}};};Chat.socket.onclose = function () {document.getElementById('chat').onkeydown = null; Console.log('Info: WebSocket closed.');};Chat.socket.onmessage = function (message) {Console.log(message.data);};});Chat.initialize = function() {if (window.location.protocol == 'http:') {Chat.connect('ws://' + window.location.host +'/examples/websocket/chat');} else {Chat.connect('wss://' + window.location.host +'/examples/websocket/chat');}};Chat.sendMessage = (function() {var message = document.getElementById('chat').value; if (message != '') {Chat.socket.send(message);document.getElementById('chat').value = '';}});var Console = {};Console.log = (function(message) {var console = document.getElementById('console');var p = document.createElement('p');p.style.wordWrap = 'break-word';p.innerHTML = message;console.appendChild(p);while (console.childNodes.length > 25) {console.removeChild(console.firstChild);}console.scrollTop = console.scrollHeight;});Chat.initialize();document.addEventListener("DOMContentLoaded", function() {// Remove elements with "noscript" class - <noscript> is not allowed in XHTMLvar noscripts =document.getElementsByClassName("noscript");for (var i = 0; i < noscripts.length; i++) {noscripts[i].parentNode.removeChild(noscripts[i]);}}, false);]]></script></head><body><div class="noscript"><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enableJavascript and reload this page!</h2></div><div><p><input type="text" placeholder="type and press enter to chat" id="chat" /></p><div id="console-container"><div id="console"/></div></div></body></html>亲自测试:如果按照以上步骤部署项目,保证能顺利运行。