本文共 7396 字,大约阅读时间需要 24 分钟。
B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式,这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为服务器不需要与客户端长时间建立一个通信链接,但不容易直接完成实时的消息推送功能,如聊天室、后台信息提示、实时更新数据等功能,但通过polling、Long polling、长连接、Flash Socket以及HTML5中定义的WebSocket能完成该功能需要。
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。Socket的英文原义是“孔”或“插座”,作为UNIX的进程通信机制。Socket可以实现应用程序间网络通信。
I. Socket可以使用TCP/IP协议或UDP协议。
TCP/IP协议II. B/S架构的系统多使用HTTP协议,HTTP协议的特点(底层通信使用Socket):
使用端口接收和发送消息,默认为80端口
websocket允许通过JavaScript建立与远程服务器的连接,从而实现客户端与服务器间双向的通信。在websocket中有两个方法:
1、send() 向远程服务器发送数据 2、close() 关闭该websocket链接 websocket监听函数: 1、onopen 当网络连接建立时触发该事件 2、onerror 当网络发生错误时触发该事件 3、onclose 当websocket被关闭时触发该事件 4、onmessage 当websocket接收到服务器发来的消息的时触发的事件,也是通信中最重要的一个监听事件。msg.data websocket还定义了一个readyState属性,这个属性可以返回websocket所处的状态: 1、CONNECTING(0) websocket正尝试与服务器建立连接 2、OPEN(1) websocket与服务器已经建立连接 3、CLOSING(2) websocket正在关闭与服务器的连接 4、CLOSED(3) websocket已经关闭了与服务器的连接 websocket的url开头是ws,如果需要ssl加密可以使用wss,当我们调用websocket的构造方法构建一个websocket对象(new WebSocket(url))的之后,就可以进行即时通信了。I. 创建chat.html页面
趣味聊天室
II. 图片资源
III. 目录结构
/** * 趣味聊天的服务端程序 * * @author mazaiting */// 声明WebSocket服务器的地址@ServerEndpoint("/chatServer")public class ChatServer { /** 是否是第一次进入 */ private boolean isFirstFlag = true; private Session session; /** 用户名 */ private String userName; /** * 记录此次聊天室的服务端有多少个连接 key代表此次客户端的Session ID,value代表此次连接对象 */ private static final HashMapconnectMap = new HashMap<>(); /** * 保存所有用户的昵称信息 key是Session ID,value才是用户名 */ private static final HashMap userMap = new HashMap<>(); /** * 服务端收到客户端连接请求,连接成功后会执行此方法 * * @param session */ @OnOpen public void start(Session session) { this.session = session; connectMap.put(session.toString(), this); } /** * 发送消息 * * @param clientMessage * 消息/用户名 * @param session * 会话 */ @OnMessage public void chat(String clientMessage, Session session) { // 消息 String message; // 判断是否为第一次发送消息 if (isFirstFlag) { // 用户名赋值 this.userName = clientMessage; // 将新进来的用户保存到用户map userMap.put(session.getId(), userName); // 构造发送给客户端的提示信息 message = htmlMessage("系统消息", userName + "进入聊天室"); // 输入昵称后,代表isFirstFlag=false isFirstFlag = false; } else { // 构造发送给客户端的提示信息 message = htmlMessage(userMap.get(session.getId()), clientMessage); } sendMessageForAll(message); } /** * ws.close()方法调用后,会触发后台的标注OnClose方法 * * @param session */ @OnClose public void close(Session session) { // 当某个用户退出时,对其他用户进行广播 String message = htmlMessage("系统消息", userMap.get(session.getId()) + "退出了聊天室"); // 用户map移除 userMap.remove(session.getId()); // 链接map移除 connectMap.remove(session.getId()); sendMessageForAll(message); } /** * 格式化消息 * @param userName 用戶名 * @param message 消息 * @return 消息 */ private String htmlMessage(String userName, String message) { StringBuffer messageBuffer = new StringBuffer(); SimpleDateFormat sFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); messageBuffer.append(" "); messageBuffer.append(""); return messageBuffer.toString(); } /** * 为所有用户发送消息 * * @param message * 消息 */ private void sendMessageForAll(String message) { // 当前对象 ChatServer client = null; // 将消息广播给所有人 for (String connectKey : connectMap.keySet()) { // 获取客户端 client = (ChatServer) connectMap.get(connectKey); // 给对应的web端发送一个文本信息 try { client.session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } ; } }}"); messageBuffer.append("" + sFormat.format(new Date()) + ""); messageBuffer.append("
"); messageBuffer.append(""); messageBuffer.append(" " + userName + ""); messageBuffer.append(""); messageBuffer.append(""); messageBuffer.append("" + message + ""); messageBuffer.append("
"); messageBuffer.append("
Pushlet 是一个开源的 Comet 框架,Pushlet 使用了观察者模型:客户端发送请求,订阅感兴趣的事件;服务器端为每个客户端分配一个会话 ID 作为标记,事件源会把新产生的事件以多播的方式发送到订阅者的事件队列里。
Pushlet是一种comet实现:在Servlet机制下,数据从server端的Java对象直接推送(push)到(动态)HTML页面,而无需任何Javaapplet或者插件的帮助。它使server端可以周期性地更新client的web页面,这与传统的request/response方式相悖。浏览器client为兼容JavaScript1.4版本以上的浏览器(如InternetExplorer、FireFox),并使用JavaScript/DynamicHTML特性。而底层实现使用一个servlet通过Http连接到JavaScript所在的浏览器,并将数据推送到后者。转载地址:http://mzmpa.baihongyu.com/