Java、WebSocket、HTML简易聊天室
来源:互联网 发布:c语言字符回车结束 编辑:程序博客网 时间:2024/05/20 21:23
WebSockt协议是一种双向通信的解决方案,减少了频繁建立连接所带来的开销,使得客户端和服务端的通信更加及时。与轮询(polling)和(Comet)技术相比,WebSockt在双端通信上有明显的优势。本文以Java、Tomcat、JavaScript实现双端通信实例。
本文所使用开发环境:Java 1.8.0_45、Tomcat 7.0.53、IDE IntelliJ IDEA 2016.3.1。开发环境搭建与项目配置方法不在本文讨论范围之内。
在进行项目开发之前,首先需要弄清楚一些基本概念,首先是WebSocket中的数据传输存在的数据有两种形式:控制帧(control frame)和数据帧(data frame)。
控制帧又分为:关闭帧(close frame) 和ping-pong帧(ping and pong frames)
- close frame:用于关闭连接
- ping and pong frames:用于检测连接情况(是协议自带的心跳检测)
数据帧又主要有文本帧(textual frame)、字节帧(binary frame)
- textual frame:接收客户端以文本形式传递的数据
- binary frame:接收客户端以二进制形式传递的数据
控制帧一般是协议自己控制和实现的操作,我们在开发中并不需要自己实现。数据帧中的文本帧是最常用的,一般可以传递格式化的字符串数据,如json、xml等。字节帧接收的数据一般经过压缩处理,如gzip、prorobuf。其实数据帧除了这两种常见类型以外,还有一种partial frame,一般用于传输大量数据,例如图片和视频。
在开发过程中,我们需要了解在WebSockt的生命周期中存在四种主要的事件:
- The open event:建立连接事件
- The message event:接收消息事件
- The error event:连接或终端出错事件
- The close event:关闭连接事件
了解了WebSocket的基本的概念以后,接着来看一下Java WebSocket的API,首先是EndPoint类的源码:
public abstract class Endpoint {紧接着在看一下继承EndPoint类实现终端接口的ProgrammaticEchoServer类代码:
public Endpoint() {
}
public abstract void onOpen(Session var1, EndpointConfig var2);
public void onClose(Session session, CloseReason closeReason) {
}
public void onError(Session session, Throwable throwable) {
}
}
public class ProgrammaticEchoServer extends Endpoint {注意:EndPoint类是没有定义message event事件的处理的,此处的message event事件响应是在onOpen方法中给Session对象添加addMessageHandler方法添加的。在实现的onMessge中,只是将接收到的字符串加工一下就直接返回给另一个终端了。
@Override
public void onOpen(Session session, EndpointConfig endpointConfig) {
Session mySession = session;
mySession.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String text) {
try {
mySession.getBasicRemote().sendText("I got (" + text + ")" + "so I am send the message back.anna");
} catch (IOException e) {
System.out.println("oh dear, something was wrong send the message back:" + e.getMessage());
}
}
});
}
@Override
public void onClose(Session session, CloseReason closeReason) {
super.onClose(session, closeReason);
}
@Override
public void onError(Session session, Throwable throwable) {
super.onError(session, throwable);
}
}
接下来我们看一下另一个终端,HTML端JavaScript部分的相关代码:
function initConnect() {首先建立WebSocket连接,建立连接以后客户端可以向服务终端发送字符串,服务端接收到以后,加工一下,直接返回,在将加工后的字符串显示在浏览器窗口。本页面的运行效果如下:
//var wsUri = "ws://localhost:8080/programmaticEcho";
var wsUri = "ws://localhost:8080/echo";
writeToScreen("Connecting to " + wsUri);
echo_websocket = new WebSocket(wsUri);
echo_websocket.onopen = function (evt) {
writeToScreen("Connected !");
};
echo_websocket.onmessage = function (evt) {
writeToScreen("Received message: " + evt.data);
};
echo_websocket.onerror = function (evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
};
}
function send_echo() {
doSend(textID.value);
}
function doSend(message) {
echo_websocket.send(message);
writeToScreen("Sent message: " + message);
}
本实例只是单纯地收发消息并显示咋在浏览器窗口上,实现了双端的收发,和及时通信的骨架代码。接下来我们看一下本实例中的聊天室实例。
聊天室代码的Java终端是使用注解实现的,具体代码如下:
@ServerEndpoint("/chatroom")注意:@OnServerEndPoint注解表示该类为实现了EndPoint的终端,后面的参数表示在发布的项目该终端的相对路径。@OnOpen注解在此处仅接受一个Session参数,但是添加了@OnOpen注解的方法最多可以有三个参数:Session session, EndPointConfig cfg, String parameters,而且这三个参数是可选无序的。后面的@OnMessage,@OnClose,@OnError注解也有这样的特性。
public class ChatRoom {
private Session session;
private List<String> names = new ArrayList<>();
private String username;
@OnOpen
public void open(Session session) {
this.username = "用户-->" + session.getId();
this.session = session;
SocketConfig.getInstance().add(this);
names.add(username);
broadCast(username + " 进入聊天室!!");
}
@OnMessage
public void receive(Session session, String msg) {
broadCast(username + ":" + new Date().toString() + msg);
}
@OnClose
public void close(Session session) {
SocketConfig.getInstance().remove(this);
names.remove(username);
broadCast(username + " 退出聊天室!!");
}
public void broadCast(String msg) {
Set<ChatRoom> sockets = SocketConfig.getInstance().getSockets();
System.out.println("sockets-->" + sockets.size());
for (Iterator iterator = sockets.iterator(); iterator.hasNext(); ) {
try {
ChatRoom chatRoom = (ChatRoom) iterator.next();
chatRoom.session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
OK~~~代码中接受到消息后,会将消息发给每一个消息给广播给每一个连接中的每一个终端。
注意:每一个终端连接创建一个EndPoint对象,一个Session代表一次会话,因此需要在创建连接以后,将Session对象存储到一个全局单例的对象中,这就是最简易的连接池。
聊天室的运行效果如下:
最后附上实例代码:https://github.com/BruceT2010/WS-Samples
0 0
- Java、WebSocket、HTML简易聊天室
- Java WebSocket编程与网页简易聊天室
- Websocket学习--简易聊天室
- WebSocket + html 实现聊天室
- 基于WebSocket的简易聊天室
- Java webSocket 网页聊天室
- java-websocket即时通讯-聊天室
- Java WebSocket 聊天室Demo
- Html Websocket搭建右下角聊天室
- 基于spring4 websocket的简易聊天室
- 基于websocket的简易聊天室的实现
- 使用Html5下WebSocket搭建简易聊天室
- 基于websocket和swoole的简易聊天室
- php基于websocket搭建简易聊天室(socket)
- Java简易聊天室
- JAVA--简易聊天室程序
- java简易多用户聊天室
- java socket简易聊天室
- Spring常用注解(一)
- 标准论文参考文献添加方法——Zotero入门使用教程
- How to catch java.lang.NoClassDefFoundError?
- C语言字符串查找基础----strchr()、strrchr()、strpbrk()、strstr()
- mac工具-终端
- Java、WebSocket、HTML简易聊天室
- 解读2016,2017年运维的风口在哪?
- WIFI无线路由器的五种工作模式
- genymotion
- 常用排序算法总结
- 1031. Hello World for U (20)
- java 反射
- Head Frist Java 图形用户接口 要点
- Charts 3.0框架绘制-柱形图表