我们是要在网页端生成小程序码,用微信扫码,点击登录后。该二维码关闭跳转到指定界面.
那就简单说一下HTTP协议,WebSocket协议. (如果对于这些协议和网络传输过程比较模糊的话,请看下这篇文章 http://blog.csdn.net/gordohu/article/details/54097841 )
WebSocket是HTML5出的(协议)可以理解为HTTP的加强版.( 推荐文章: http://blog.csdn.net/frank_good/article/details/50856585 )
HTTP:链接分为短链接,长链接,短链接是每次请求都要三次握手才能发送自己的信息。即每一个request对应一个response。长链接是在一定的期限内保持链接。保持TCP连接不断开。客户端与服务器通信,必须要有客户端发起然后服务器返回结果。客户端是主动的,服务器是被动的。
WenSocket:建立了WenSocket之后服务器不必在浏览器发送request请求之后才能发送信息到浏览器。这时的服务器已有主动权想什么时候发就可以发送信息到服务器。而且信息当中不必再带有head的部分信息了,与http的长链接通信来说,这种方式,不仅能降低服务器的压力。而且信息当中也减少了部分多余的信息。
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
环境,我们是Grails 框架.需要通过 intellij idea 中的 Terminal 命令框输入命令:grails install-templates.会在项目目录下出现web.xml.( 使用Grails 不清楚的 推荐: http://blog.csdn.net/fengbaozonghuiguoqu/article/details/77770999 ) 引入
Servlet配置的基类.
package websocket;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
@WebServlet(urlPatterns = { "/zy" }) //注解简化
public class SocketService extends WebSocketServlet {
private static final long serialVersionUID = 1L;
public String getId(HttpServletRequest request){
String webSocketId = request.getParameter("webSocketId");
System.out.println("@@建立连接webSocketId="+webSocketId);
return webSocketId;
}
@Override
protected StreamInbound createWebSocketInbound(String arg0,
HttpServletRequest request) {
return new SocketServiceInbound(this.getId(request));
}
}
socket操作类
package websocket;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class SocketServiceUtil {
// 保存连接的MAP容器
private static final Map connections = new HashMap();
/**
* 向连接池中添加连接
* @param inbound
*/
public static void addMessageInbound(SocketServiceInbound inbound) {
System.out.println("id : " + inbound.getId() + " join..");
connections.put(inbound.getId(), inbound);
}
/**
* 移除连接池中的连接
* @param id 用户名
*/
public static void removeMessageInbound(String id) {
System.out.println("id : " + id + " exit..");
connections.remove(id);
}
/**
* 获取所有的在线用户
* @return
*/
public static Set getOnlineId() {
return connections.keySet();
}
/**
* 向指定的用户发送消息
* @param id 用户名
* @param message 消息
*/
public static void sendMessageToUser(String id, String message) {
try {
// 向特定的用户发送数据
System.out.println("send message to id : " + id
+ " ,message content : " + message);
SocketServiceInbound inbound = connections.get(id);
if (inbound != null) {
inbound.getWsOutbound().writeTextMessage(
CharBuffer.wrap(message));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 向所有的用户发送消息
* @param message 消息
*/
public static void sendMessageToAll(String message) {
try {
Set keySet = connections.keySet();
for (String key : keySet) {
SocketServiceInbound inbound = connections.get(key);
if (inbound != null) {
System.out.println("send message to user : " + key
+ " ,message content : " + message);
inbound.getWsOutbound().writeTextMessage(
CharBuffer.wrap(message));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
静态常量Map
链接消息绑定.继承MessageInbound 自定义String id ,与Util中参数数据结构一致.
package websocket;
import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
public class SocketServiceInbound extends MessageInbound {
// 当前连接的用户名称
private final String id;
public SocketServiceInbound(String id) {
this.id = id;
}
public String getId() {
return this.id;
}
@Override
protected void onOpen(WsOutbound outbound) {
// TODO Auto-generated method stub
//向连接池添加当前的连接对象
SocketServiceUtil.addMessageInbound(this);
//向当前连接发送当前在线用户的列表
//SocketServiceUtil.sendMessageToUser(this.user, "uuuuuuuuuu");
}
@Override
protected void onClose(int status) {
// TODO Auto-generated method stub
// 触发关闭事件,在连接池中移除连接
SocketServiceUtil.removeMessageInbound(this.id);
}
@Override
protected void onTextMessage(CharBuffer message) throws IOException {
// TODO Auto-generated method stub
SocketServiceUtil.sendMessageToUser(this.id, message.toString());
}
@Override
protected void onBinaryMessage(ByteBuffer arg0) throws IOException {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Binary message not supported.");
}
}
继承后的方法的重写 可直接在页面中调用.eg:如下
<%@ page contentType="text/html;charset=UTF-8" %>
WebSocket Demo
webSocket的四种状态:
CONNECTING:值为0,表示正在连接。
OPEN:值为1,表示连接成功,可以通信了。
CLOSING:值为2,表示连接正在关闭。
CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
测试一下.(这里测试消息的发送,回调)
1:下面就启动项目初始化Servlet,访问页面,创建id为"hujunbao"的链接.
查看回调信息websocket.onopen 和 websocket.onerror反馈!
2:“链接成功” or “链接失败”
3:服务器高兴的时候就向客户端发送message:“testMessageToJunBao” or “testMessageToAll” …根据消息不同,做出相对应的业务!
4:业务完成后可在业务中关闭,或者添加监听事件,来控制链接状态.