websocket 聊天室搭建技术点
2015-12-18 15:44
525 查看
spring 配置:
依赖包:
nginx 配置
upstream home-dev-ws{ server IP: port; }
#websocket 需要加下这个 map $http_upgrade $connection_upgrade { default upgrade; '' close; }
server { listen 80; server_name xxxxx.com
rewrite ^(.*)/__dev/?$ /__dev/; if ( $http_cookie ~* "(.*)$") { set $user_cookie $1; }
location /room/chat {
proxy_pass http://home-dev-ws; proxy_redirect off;
proxy_read_timeout 43200; keepalive_timeout 600; # 链接保持的时间 proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
}
}
socket 链接已经信息处理handler:
拦截器:
交互界面------
<bean id="websocket" class="com.xxxxx.controller.socket.SocketHandler"/> <websocket:handlers> <websocket:mapping path="/room/chat" handler="websocket"/> <websocket:handshake-interceptors> <bean class="com.xxxx.controller.socket.HandshakeInterceptor"/> </websocket:handshake-interceptors> </websocket:handlers>
依赖包:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.version}</version> </dependency>
nginx 配置
upstream home-dev-ws{ server IP: port; }
#websocket 需要加下这个 map $http_upgrade $connection_upgrade { default upgrade; '' close; }
server { listen 80; server_name xxxxx.com
rewrite ^(.*)/__dev/?$ /__dev/; if ( $http_cookie ~* "(.*)$") { set $user_cookie $1; }
location /room/chat {
proxy_pass http://home-dev-ws; proxy_redirect off;
proxy_read_timeout 43200; keepalive_timeout 600; # 链接保持的时间 proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
}
}
socket 链接已经信息处理handler:
public class SocketHandler extends TextWebSocketHandler { private final static Logger logger = LoggerFactory.getLogger(SocketHandler.class); private static Map<String, UserWebSocketSession> users= new HashMap<>(); //所有在线用户 private static Map<String, Set<String>> rooms = new HashMap<>(); //所有房间 private final static String roomId = "12345"; /** * 在UI在用js调用websocket.send()时候,会调用该方法 */ @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { super.handleTextMessage(session, message); UserWebSocketSession userWebSocketSession = users.get(session.getId()); if(userWebSocketSession != null && userWebSocketSession.getRoomId() != null){ Set<String> room = rooms.get(userWebSocketSession.getRoomId()); logger.info("----12---room:{}"+ JsonUtil.toJSON(room)); if(room == null || room.size() <= 0){ return; } sendMessageToUsers(session, room, message); logger.info("----------1"); }else { logger.error("current_user could not send messege userWebSocketSession:{}", JsonUtil.toJSON(userWebSocketSession)); } } /** * 连接成功时候,会触发UI上onopen方法 */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { if(users.get(session.getId()) == null){ UserWebSocketSession userWebSocketSession = new UserWebSocketSession(); userWebSocketSession.setRoomId(roomId); userWebSocketSession.setSession(session); users.put(session.getId(), userWebSocketSession); Set<String> room = rooms.get(roomId); if(room == null){ room = new HashSet<>(); rooms.put(roomId, room); } logger.info("----====-----rooms:{}" + JsonUtil.toJSON(rooms)); room.add(session.getId()); logger.info("---------------room:{}" + JsonUtil.toJSON(room)); logger.info("new user ====session_id:{}", session.getId()); } logger.info("connect to the websocket success..... ."); } /** * Handle an error from the underlying WebSocket message transport. * @param session * @param exception * @throws Exception */ @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { UserWebSocketSession userSession= users.get(session.getId()); if(userSession == null){ return; } Set<String> room = rooms.get(userSession.getRoomId());//查找所在房间 room.remove(session.getId());//从房间中去除 if(room.size() <=0){ //房间没人,清除房间 rooms.remove(userSession.getRoomId()); } users.remove(session.getId());//从在线用户列表里移除 logger.info("websocket connection closed......"); } /** * Invoked after the WebSocket connection has been closed by either side, * or after a transport error has occurred. Although the session may technically still be open, * depending on the underlying implementation, sending messages at this point is discouraged and most likely will not succeed. * @param session * @param closeStatus * @throws Exception */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) { logger.info("----close---11-closeStatus:{} session-status:{}__ user_lise:{}", JsonUtil.toJSON(closeStatus), session.isOpen(), users.size()); UserWebSocketSession userSession= users.get(session.getId()); if(userSession == null){ return; } Set<String> room = rooms.get(userSession.getRoomId());//查找所在房间 room.remove(session.getId()); //从房间中去除 if(room.size() <=0){ //房间没人,清除房间 rooms.remove(userSession.getRoomId()); } users.remove(session.getId()); //从在线用户列表里移除 logger.info("----------1111_ user_size:{}"+users.size() ); } /* Whether the WebSocketHandler handles partial messages. If this flag is set to true and the underlying WebSocket server supports partial messages, then a large WebSocket message, or one of an unknown size may be split and maybe received over multiple calls to WebSocketHandler.handleMessage(WebSocketSession, WebSocketMessage). The flag WebSocketMessage.isLast() indicates if the message is partial and whether it is the last part. */ @Override public boolean supportsPartialMessages() { logger.info("websocket connection supportsPartialMessages......"); return false; } /** * 给某个用户发送消息 * @param currentSession * @param message */ public void sendMessageToUsers(WebSocketSession currentSession, Set<String> sessionIdSet, TextMessage message) { logger.info("currentSession_id:{}=======sessionIdSet:{}", currentSession.getId(), sessionIdSet.size()); Iterator<String> iterator = sessionIdSet.iterator(); while (iterator.hasNext()) { String sessionId = iterator.next(); if(sessionId.equals(currentSession.getId())){//信息不发给自己 continue; } UserWebSocketSession user = users.get(sessionId); String fromUserName = user.getUserName(); WebSocketSession userSession = user.getSession(); logger.info("-send to--session_id:{}, user_name:{}", userSession.getId(), fromUserName); if (!userSession.equals(currentSession)) { if (userSession.isOpen()) { sendMessageToUser(userSession, fromUserName, message); } } } } /** * 给某个用户发送消息 * * @param message */ public void sendMessageToUser(WebSocketSession userSession, String userName, TextMessage message) { logger.info("======send message to session_id:{}: name:{}", userSession.getId(), userName); if(userSession != null && userSession.isOpen()){ TextMessage returnMessage = new TextMessage(new DateTime().toString("HH:mm:ss")+"/<br>"+(userName != null? userName:"")+" "+message.getPayload()); try { userSession.sendMessage(returnMessage); } catch (IOException e) { e.printStackTrace(); } } } }
拦截器:
HandshakeInterceptor
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { boolean b = super.beforeHandshake(request, response, wsHandler, attributes); System.out.println("Before Handshake=====:"+ b); return b; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { super.afterHandshake(request, response, wsHandler, ex); System.out.println("after Handshake=====: 1"); } }
交互界面------
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!doctype html> <html> <head> <title>WebSocket/SockJS Echo Sample (Adapted from Tomcat's echo sample)</title> <style type="text/css"> #connect-container { float: left; width: 400px } #connect-container div { padding: 5px; } #console-container { float: left; margin-left: 15px; 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 src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>--%> <script type="text/javascript"> var ws = null; var url = null; var transports = []; function setConnected(connected) { document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('echo').disabled = !connected; } function connect() { alert("url:"+url); if (!url) { alert('Select whether to use W3C WebSocket or SockJS'); return; } ws = (url.indexOf('sockjs') != -1) ? new SockJS(url, undefined, {protocols_whitelist: transports}) : new WebSocket(url); ws.onopen = function () { setConnected(true); log('Info: connection opened.'); }; ws.onmessage = function (event) { // log('Received: ' + event.data); log(event.data); }; ws.onclose = function (event) { setConnected(false); log('Info: connection closed.'); log(event); }; } function disconnect() { if (ws != null) { ws.close(); ws = null; } setConnected(false); } function echo() { if (ws != null) { var message = document.getElementById('message').value; // log('Sent: ' + message); log( message); ws.send(message); } else { alert('connection not established, please connect.'); } } function updateUrl(urlPath) { if (urlPath.indexOf('sockjs') != -1) { url = urlPath; document.getElementById('sockJsTransportSelect').style.visibility = 'visible'; } else { if (window.location.protocol == 'http:') { url = 'ws://' + window.location.host + urlPath; } else { url = 'wss://' + window.location.host + urlPath; } document.getElementById('sockJsTransportSelect').style.visibility = 'hidden'; } } function updateTransport(transport) { alert(transport); transports = (transport == 'all') ? [] : [transport]; } function log(message) { var console = document.getElementById('console'); var p = document.createElement('p'); p.style.wordWrap = 'break-word'; p.appendChild(document.createTextNode(message)); console.appendChild(p); while (console.childNodes.length > 25) { console.removeChild(console.firstChild); } console.scrollTop = console.scrollHeight; } </script> </head> <body> <noscript> <h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable Javascript and reload this page!</h2> </noscript> <div> <div id="connect-container"> <input id="radio1" type="radio" name="group1" onclick="updateUrl('/room/chat');"> <label for="radio1">W3C WebSocket</label> <br> <input id="radio2" type="radio" name="group1" onclick="updateUrl('/room/chat');"> <label for="radio2">SockJS</label> <div id="sockJsTransportSelect" style="visibility:hidden;"> <span>SockJS transport:</span> <select onchange="updateTransport(this.value)"> <option value="all">all</option> <option value="websocket">websocket</option> <option value="xhr-polling">xhr-polling</option> <option value="jsonp-polling">jsonp-polling</option> <option value="xhr-streaming">xhr-streaming</option> <option value="iframe-eventsource">iframe-eventsource</option> <option value="iframe-htmlfile">iframe-htmlfile</option> </select> </div> <div> <button id="connect" onclick="connect();">进入房间</button> <button id="disconnect" disabled="disabled" onclick="disconnect();">退出房间</button> </div> <div> <textarea id="message" style="width: 350px">Here is a message!</textarea> </div> <div> <button id="echo" onclick="echo();" disabled="disabled">发送</button> </div> </div> <div id="console-container"> <div id="console"></div> </div> </div> </body> </html>
相关文章推荐
- 2015-2016网页设计趋势分析 Web Design of Trends
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 实用的利用 CSS + <em>标签 来完成一个三角形的制作
- JavaScript中“+”的陷阱深刻理解
- ASP + Serv-u 实现FTP的代码
- css静态滤镜 + A:Hover 效果第1/3页
- 浅析nodejs实现Websocket的数据接收与发送
- javascript中加号(+)操作符的一些神奇作用
- 基于html5和nodejs相结合实现websocket即使通讯
- php使用websocket示例详解
- php+html5基于websocket实现聊天室的方法
- Javascript WebSocket使用实例介绍(简明入门教程)
- java中实现兼容ie6 7 8 9的spring4+websocket
- HTML5之WebSocket入门3 -通信模型socket.io
- Python实现同时兼容老版和新版Socket协议的一个简单WebSocket服务器
- Python通过websocket与js客户端通信示例分析
- Python列表append和+的区别浅析
- windows+ubuntu双系统重新安装windows后的引导修复 3ff0
- dubbo + spring + mybaits 的pom文件列一
- IM 协议的分析和选取 (XMPP&WebSocket)