Websocket简述

释义:

WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

为什么需要 WebSocket:

了解计算机网络协议的人,应该都知道:HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。

这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。

这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步JavaScript和XML(AJAX)请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。

因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高

利用javax.websocket实现websocket的案例如下:

消息发送端:

String pushMsg = JSON.toJSONString(msgVo,SerializerFeature.DisableCircularReferenceDetect);
String url = ws://192.168.11.215:8082/websocket/weionwall/"+barId+"/false";
//推送消息
WebSocketClientThread clientThread = new WebSocketClientThread(url,pushMsg);
Thread thread = new Thread(clientThread);
thread.start();

WebSocketClientThread类:

/**
 * websocket客户端
 *
 */
public class WebSocketClientThread implements Runnable {
	
	private static final Log logger = LogFactory.getLog(WebSocketClientThread.class);
	
	private String url;
	private String msg;
	public WebSocketClientThread(String url, String msg) {
		super();
		this.url = url;
		this.msg = msg;
	}


	public void run() {
		sendMsg(1);
	}
	
	public void sendMsg(int i){
		i++;
		try {
			MyWebSocketClient client = new MyWebSocketClient(new URI(url), msg);
			client.connect();
		} catch (Exception e) {
			logger.error(e.fillInStackTrace());
			e.printStackTrace();
			if(i<=10){
				sendMsg(i);
			}
		}
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}
	
}

MyWebSocketClient类:

package com.dflm.weixin.util;

import java.net.URI;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ServerHandshake;

public class MyWebSocketClient extends WebSocketClient {
	
	private static final Log logger = LogFactory.getLog(MyWebSocketClient.class);
	
	private String msg;

	public MyWebSocketClient(URI serverUri, Draft draft, String msg) {
		super(serverUri, draft);
		this.msg = msg;
	}

	public MyWebSocketClient(URI serverURI, String msg) {
		super(serverURI);
		this.msg = msg;
	}

	@Override
	public void onOpen(ServerHandshake handshakedata) {
		this.send(msg);
	}

	@Override
	public void onMessage(String message) {
		this.close();
	}

	@Override
	public void onFragment(Framedata fragment) {
	}

	@Override
	public void onClose(int code, String reason, boolean remote) {
		if(!remote){
			logger.info("MyWebSocketClient closed by " + ( remote ? "remote peer" : "us" ));
		}
		
	}

	@Override
	public void onError(Exception ex) {
		ex.printStackTrace();
	}
}

WeionwallWebSocket类:

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 *                 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint("/websocket/weionwall/{bid}/{isAdmin}")
public class WeionwallWebSocket{
	
	/**
	 * 连接建立成功调用的方法
	 * 
	 * @param session
	 *            可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
	 */
	@OnOpen
	public void onOpen(Session session, @PathParam(value = "bid") String bid,
			@PathParam(value = "isAdmin") Boolean isAdmin) {
		if(isAdmin == null){
			isAdmin = false;
		}
		if(StringUtil.isNotBlank(bid)&&isAdmin){
			SessionUtil.putOnwallAdminSession(bid, session);
		}
		if(StringUtil.isNotBlank(bid)&&!isAdmin){
			SessionUtil.putOnwallUserSession(bid, session);
		}
	}

	/**
	 * 连接关闭调用的方法
	 */
	@OnClose
	public void onClose(@PathParam(value = "bid") String bid,
			@PathParam(value = "isAdmin") Boolean isAdmin,Session session) {
		if(isAdmin == null){
			isAdmin = false;
		}
		if(StringUtil.isNotBlank(bid)&&isAdmin){
			SessionUtil.removeOnwallAdminSession(bid, session);
		}
		if(StringUtil.isNotBlank(bid)&&!isAdmin){
			SessionUtil.removeOnwallUserSession(bid, session);
		}
	}

	/**
	 * 收到客户端消息后调用的方法
	 * 
	 * @param message
	 *            客户端发送过来的消息
	 */
	@OnMessage
	public void onMessage(String message,@PathParam(value="bid") String bid) {
		if(StringUtil.isNotEmpty(message)){
			JSONObject object = JSONObject.parseObject(message);
			Boolean isCheck = object.getBoolean("isCheck");
			if(isCheck == null){
				isCheck = false;
			}
			if(isCheck){
				if(SessionUtil.onWallAdminSessionMap!=null&&!SessionUtil.onWallAdminSessionMap.isEmpty()){
					Set<Session> set = SessionUtil.onWallAdminSessionMap.get(bid);
					if(set!=null&&!set.isEmpty()){
						for(Session session : set){
							try {
								session.getAsyncRemote().sendText(message);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					}
				}
			}else{
				if(SessionUtil.onWallUserSessionMap!=null&&!SessionUtil.onWallUserSessionMap.isEmpty()){
					if(message.contains("type\":\"redBag")){
						String cashRedType = null;
						JSONArray array = (JSONArray) object.get("normal");
						JSONArray barIdList = (JSONArray)object.get("barIdList");
						if(array!=null && array.size()>0)
						{
							JSONObject obj = (JSONObject) array.get(0);
							cashRedType = obj.getString("cashRedType");
						}
						if(StringUtil.isNotBlank(cashRedType))
						{
							if("2".equals(cashRedType))
							{
								Set<String> bidSet = SessionUtil.onWallUserSessionMap.keySet();
								for (String barid : bidSet) {
									if(barIdList!=null && barIdList.contains(barid)) {
										Set<Session> set = SessionUtil.onWallUserSessionMap.get(barid);
										if(set!=null&&!set.isEmpty()){
											for(Session session : set){
												try {
													synchronized (session){ 
													session.getAsyncRemote().sendText(message);
													}
												} catch (Exception e) {
													e.printStackTrace();
												}
											}
										}
									}
								}
							}else {
								Set<Session> set = SessionUtil.onWallUserSessionMap.get(bid);
								if(set!=null&&!set.isEmpty()){
									for(Session session : set){
										try {
												session.getAsyncRemote().sendText(message);
										} catch (Exception e) {
											e.printStackTrace();
										}
									}
								}
							}
						}else {
							Set<Session> set = SessionUtil.onWallUserSessionMap.get(bid);
							if(set!=null&&!set.isEmpty()){
								for(Session session : set){
									try {
											session.getAsyncRemote().sendText(message);
									} catch (Exception e) {
										e.printStackTrace();
									}
								}
							}
						}
					}else
					{
						Set<Session> set = SessionUtil.onWallUserSessionMap.get(bid);
						if(set!=null&&!set.isEmpty()){
							for(Session session : set){
								try {
										session.getAsyncRemote().sendText(message);
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
						}
					}
				}
			}
		}
	}

	/**
	 * 发生错误时调用
	 * 
	 * @param session
	 * @param error
	 */
	@OnError
	public void onError(Session session, Throwable error,@PathParam(value = "bid") String bid,
			@PathParam(value = "isAdmin") Boolean isAdmin) {
		if(isAdmin == null){
			isAdmin = false;
		}
		if(StringUtil.isNotBlank(bid)&&isAdmin){
			SessionUtil.removeOnwallAdminSession(bid, session);
		}
		if(StringUtil.isNotBlank(bid)&&!isAdmin){
			SessionUtil.removeOnwallUserSession(bid, session);
		}
	}
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值