本帖最后由 我是楠楠 于 2017-8-17 16:39 编辑
对于所有的基于服务端的C/S 应用,http请求仅支持请求-响应模式,限制太大,服务器无法主动发送消息给客户端,WebSocket协议既可以由服务端发起消息,也可以由客户端发起请求。 HTTP协议与WebSocket协议声明周期比较:
HTTP | | | 客户端通过发送一个http请求初始化连接 服务端做一次响应 连接建立,这条连接就是对称的 两端都可以发送和接收消息 任何一端都可以关闭连接 |
websocket是基于http协议的扩展,支持长连接。服务器端需要tomcat7以上 协议请求地址测试 public static final String WEBSOCKET = "ws://qp.hystudio.cn:9000"; 网页测试地址:http://qp.hystudio.cn:9000/service/service.htm 如果使用多客户端同时使用支持WEBSOCKET的服务端,连接方式如下:
WEBSOCKET使用步骤 1/创建一个websocket连接对象 mConnection = new WebSocketConnection(); 2/创建监听器继承WebSocketConnectionHandler public class WebSocketConnectListener extends WebSocketConnectionHandler {} 3/需要和服务器创建消息通道,用于和服务器的数据交互,可以发送和接收数据 public void connect() { if (!isConnect()) { connectListener = new WebSocketConnectListener(context,mConnection, message, listener); try { mConnection.connect(WebSocket+path, connectListener); } catch (WebSocketException e) { e.printStackTrace(); } } } 4/与服务器发送消息前需要判断是否连接 public boolean isConnect() { if (mConnection == null) return false; return mConnection.isConnected(); } 5/客户端与服务器连接成功后测试发送消息接口 public void sendTextMessage(String sendText) { if (mConnection == null) { return; } connect(); mConnection.sendTextMessage(sendText); } 6/由于是基于http协议。也可以作为普通的request请求使用 //连接建立成功 @Override public void onOpen() { super.onOpen(); LogUtils.d("%s", "WebSocketConnectListener connect"); connection.sendTextMessage(message); }
//连接断开(一般情况下是由于网络断开,或者请求参数出错) @Override public void onClose(int code, String reason) { super.onClose(code, reason); LogUtils.d("%s", "WebSocketConnectListener lost"); if (this.listener != null) { this.listener.onClose(code, reason); } }
//收到服务器消息时使用 @Override public void onTextMessage(String payload) { super.onTextMessage(payload); LogUtils.d("%s", "payload = " + payload); if (this.listener != null) { this.listener.onSuccess(payload); } }
作为一个普通的请求方式,类似http请求方式。这里自定义协议对象,封装请求参数后进行请求 IRequest tokenRequest = new TokenRequest(context, App.getInstance().getDeviceId(), new IRequestListener() { @Override public void onSuccess(String payload) { TokenResponse response = JsonUtils.fromJson(payload, TokenResponse.class); if (response.isRequestSuccssful()) { DBAdapter.getInstance().addToken(response.toToken()); App.getInstance().setToken(response.toToken()); setToken(response.toToken().getToken()); request.request(); } else { SnackbarUtils.show((Activity) context, R.string.device_unauth); } } @Override public void onClose(int code, String reason) { } }); tokenRequest.request();
这里TokenRequest对象仅仅是封装了协议请求参数。详细如下 @Path(Constants.Path.TOKENPATH) public class TokenRequest extends IRequest { private String deviceId; public TokenRequest(Context context, String deviceID, IRequestListener listener) { super(context, listener); this.deviceId = deviceID; }
@Override protected String prapareMsg() { return "{" + "deviceId:" + deviceId + "}"; } }
这里是基于WEBSOCKET协议完成了一次普通的http请求。它最大的优势是和服务端建立的双向通道,既可以由客户端发起请求,也可以由服务端发起请求。之前自主研发消息推送基本上都是由客户端轮询方式,效率低并且浪费资源。HTTP请求的请求头是很长的,但是和服务器建立连接时可能发送的是一个很少的数据,这样也是占用了服务器资源。WEBSOCKET是保证只要在服务端和客户端建立连接后任何一端发起消息,相互推送消息,效率也是极大的提高了,并且服务端和客户端之间的标头信息很小,可以降低服务端的资源浪费。 |