websocket的学习及坑

最近项目上需要优化,原来的方法是通过http请求来获取数据,但是客户觉得速度不够快,一番思索后,决定用websocket实时传输数据。

准备知识:websocket是什么,为什么要用websocket,如何使用websocket。

WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。

WebSocket的使用,需要前端与后台配合,前端代码比较简单。

<!DOCTYPE html>  
<meta charset="utf-8" />  
<title>WebSocket Test</title>  
<script language="javascript"type="text/javascript">  
    var wsUri ="ws://echo.websocket.org/"; 
    var output;  
    
    function init() { 
        output = document.getElementById("output"); 
        testWebSocket(); 
    }  
 
    function testWebSocket() { 
        websocket = new WebSocket(wsUri); 
        websocket.onopen = function(evt) { 
            onOpen(evt) 
        }; 
        websocket.onclose = function(evt) { 
            onClose(evt) 
        }; 
        websocket.onmessage = function(evt) { 
            onMessage(evt) 
        }; 
        websocket.onerror = function(evt) { 
            onError(evt) 
        }; 
    }  
 
    function onOpen(evt) { 
        writeToScreen("CONNECTED"); 
        doSend("WebSocket rocks"); 
    }  
 
    function onClose(evt) { 
        writeToScreen("DISCONNECTED"); 
    }  
 
    function onMessage(evt) { 
        writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>'); 
        websocket.close(); 
    }  
 
    function onError(evt) { 
        writeToScreen('<span style="color: red;">ERROR:</span> '+ evt.data); 
    }  
 
    function doSend(message) { 
        writeToScreen("SENT: " + message);  
        websocket.send(message); 
    }  
 
    function writeToScreen(message) { 
        var pre = document.createElement("p"); 
        pre.style.wordWrap = "break-word"; 
        pre.innerHTML = message; 
        output.appendChild(pre); 
    }  
 
    window.addEventListener("load", init, false);  
</script>  
<h2>WebSocket Test</h2>  
<div id="output"></div>  
</html>

后台可以选择的websocket的接口比较多,这里使用的是java。

package com.websocket;

//import org.java_websocket.WebSocketImpl;   //main方法中使用
import org.java_websocket.handshake.ClientHandshake;  
import org.java_websocket.server.WebSocketServer;  
  

import java.net.InetSocketAddress;  
import java.net.UnknownHostException;

public class WebSocket extends WebSocketServer{
	int j=0;  
    int h=0;  
    int e=0;  
    int l=0;  
  
    public WebSocket(InetSocketAddress address) {  
        super(address);  
        System.out.println("地址" + address);  
    }  
  
    public WebSocket(int port) throws UnknownHostException {  
        super(new InetSocketAddress(port));  
        System.out.println("端口" + port);  
    }  
  
    /** 
     * 触发连接事件 
     * @param conn 
     * @param handshake 
     */  
    @Override  
    public void onOpen(org.java_websocket.WebSocket conn, ClientHandshake handshake) {  
        System.out.println("有人连接Socket conn:" + conn);  
        l++;  
    }  
  
    /** 
     * 触发关闭事件 
     * @param conn 
     * @param message 
     * @param reason 
     * @param remote 
     */  
    @Override  
    public void onClose(org.java_websocket.WebSocket conn, int message, String reason, boolean remote) {  
        userLeave(conn);  
    }  
  
    /** 
     * 客户端发送消息到服务器是触发事件 
     * @param conn 
     * @param message 
     */  
    @Override  
    public void onMessage(org.java_websocket.WebSocket conn, String message) {  
        if(message != null) {  
            //将用户加入  
            this.userJoin(message, conn);  
        }  
    }  
  
    /** 
     * 触发异常事件 
     * @param conn 
     * @param message 
     */  
    @Override  
    public void onError(org.java_websocket.WebSocket conn, Exception message) {  
        System.out.println("Socket异常:" + message.toString());  
        e++;  
    }

    public void onStart() {
        
    }

    /** 
     * 用户下线处理 
     * @param conn 
     */  
    public void userLeave(org.java_websocket.WebSocket conn) {  
        String user = WebSocketPool.getUserByKey(conn);  
        boolean b = WebSocketPool.removeUser(conn); // 在连接池中移除连接  
        if (b) {  
            WebSocketPool.sendMessage(user); // 把当前用户从所有在线用户列表中删除  
            String leaveMsg = "[系统]" + user + "下线了";  
            WebSocketPool.sendMessage(leaveMsg); // 向在线用户发送当前用户退出的信息  
        }  
    }  
  
    public void userJoin(String user, org.java_websocket.WebSocket conn) {  
        WebSocketPool.sendMessage(user); // 把当前用户加入到所有在线用户列表中  
        String joinMsg = "[系统]" + user + "上线了!";  
        WebSocketPool.sendMessage(joinMsg); // 向所有在线用户推送当前用户上线的消息  
        WebSocketPool.addUser(user, conn); // 向连接池添加当前的连接的对象  
        WebSocketPool.sendMessageToUser(conn, WebSocketPool.getOnlineUser().toString());  
        // 向当前连接发送当前在线用户的列表  
    }  
  
    public static void main(String[] args) throws InterruptedException{  
//        System.out.println("开始启动webSocket");  
//        WebSocketImpl.DEBUG = false;  
//        int port = 8080; // 端口随便设置,只要不跟现有端口重复就可以了  
//        WebSocket s =null;  
//        try {  
//            s = new WebSocket(port);  
//            s.start();  
//        } catch (UnknownHostException e1) {  
//            System.out.println("启动webSocket失败!");  
//            e1.printStackTrace();  
//        }  
//        System.out.println("启动webSocket成功!");  
    }  
}
package com.websocket;
import java.util.*;  
import org.java_websocket.WebSocket;  
public class WebSocketPool {
	private static final Map<WebSocket, String> userconnections = new HashMap<WebSocket, String>();  
	  
    /** 
     * 获取用户名 
     * @param conn 
     * @return 
     */  
    public static String getUserByKey(WebSocket conn) {  
        return userconnections.get(conn);  
    }  
  
    /** 
     * 获取在线总数 
     * @return 
     */  
    public static int getUserCount() {  
        return userconnections.size();  
    }  
  
    /** 
     * 获取WebSocket 
     * @param user 
     * @return 
     */  
    public static WebSocket getWebSocketByUser(String user) {  
        Set<WebSocket> keySet = userconnections.keySet();  
        synchronized (keySet) {  
            for (WebSocket conn : keySet) {  
                String cuser = userconnections.get(conn);  
                if (cuser.equals(user)) {  
                    return conn;  
                }  
            }  
        }  
        return null;  
    }  
  
    /** 
     * 向连接池中添加连接 
     * @param user 
     * @param conn 
     */  
    public static void addUser(String user, WebSocket conn) {  
        userconnections.put(conn, user); // 添加连接  
    }  
  
    /** 
     * 获取所有的在线用户 
     * @return 
     */  
    public static Collection<String> getOnlineUser() {  
        List<String> setUsers = new ArrayList<String>();  
        Collection<String> setUser = userconnections.values();  
        for (String u: setUser) {  
            setUsers.add(u);  
        }  
        return setUsers;  
    }  
  
    /** 
     * 移除连接池中的连接 
     * @param conn 
     * @return 
     */  
    public static boolean removeUser(WebSocket conn) {  
        if (userconnections.containsKey(conn)) {  
            userconnections.remove(conn); // 移除连接  
            return true;  
        } else  
            return false;  
    }  
  
    /** 
     * 向特定的用户发送数据 
     * @param conn 
     * @param message 
     */  
    public static void sendMessageToUser(WebSocket conn, String message) {  
        if (null != conn) {  
            conn.send(message);  
        }  
    }  
  
  
    public static void sendMessage(String message) {  
        Set<WebSocket> keySet = userconnections.keySet();  
        synchronized (keySet) {  
            for (WebSocket conn : keySet) {  
                String user = userconnections.get(conn);  
                if (user != null) { conn.send(message);  
                }  
            }  
        }  
    }  
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lgbisha

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值