WebSocket 是独立的、创建在 TCP 上的协议。Websocket 通过HTTP/1.1 协议的101状态码进行握手。为了创建Websocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)。
大家都知道客户端怎么去服务端去获取消息,http请求,webservice等等,都是主动由客户端去主动请求来的,怎么满足服务端去主动给客户端发消息。
这就来说说WebSocket
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- 添加Servlet支持 -->
<!-- 增加fastjson-1.1.34.jar --> <!-- 转json --> </dependencies> |
package com.zkb.vo;
public class ContentVo {
private String to;
private String msg;
private Integer type;
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
}
package com.zkb;
import java.util.Set;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
/**
* webSocket的核心配置类。
* @author zkb
*/
public class ServerConfig implements ServerApplicationConfig {
@Override
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scan) {
return scan;
}
@Override
public Set<ServerEndpointConfig> getEndpointConfigs(
Set<Class<? extends Endpoint>> point) {
return null;
}
}
package com.zkb;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;
import com.zkb.vo.ContentVo;
/**
* chatSocket Websocket连接入口,通道
* @author zkb
*/
@ServerEndpoint("pms/chatSocket")
public class ChatSocket {
private static Set<ChatSocket> sockets=new HashSet<ChatSocket>();
private Session session;
private static Map<String, Session> map=new HashMap<String, Session>();
private static List<String>names=new ArrayList<String>();
private String username;
private Gson gson=new Gson();
/*
* WebSocket打开连接
*/
@OnOpen
public void open(Session session){
this.session = session;
sockets.add(this);
String queryString = session.getQueryString();
this.username = queryString.substring(queryString.indexOf("=")+1);
boolean bool = names.contains(this.username); //判断这个客户端是否已经连接
if(!bool){ //不存在就添加
names.add(this.username); //发到在线客户端集合
}else{
map.remove(this.username); //存在先移除以前这个客户端的session
}
map.put(this.username, this.session);
}
/*
* 退出登录
*/
@OnClose
public void close(Session session){
//移除退出登录客户端的通信管道
sockets.remove(this);
//将客户端从names中剔除
names.remove(this.username);
}
/*
* 接收客户端发送过来的消息,然后判断是广播还是单聊
*/
@OnMessage
public void receive(Session session,String msg) throws IOException{
//将客户端消息转成json对象
ContentVo vo = gson.fromJson(msg, ContentVo.class);
//如果是群播,就像消息广播给所有人
if(vo.getType()==1){
broadcast(sockets, vo.getMsg());
}else{//如果是单推,就针对人来推
//根据单聊对象的名称拿到要单聊对象的Session
Session to_session = map.get(vo.getTo());
//如果是单聊,就将消息发送给对方
to_session.getBasicRemote().sendText(vo.getMsg());
}
}
/*
* 广播消息
*/
public void broadcast(Set<ChatSocket>sockets ,String msg){
//遍历当前所有的连接管道,将通知信息发送给每一个管道
for(ChatSocket socket : sockets){
try {
//通过session发送信息
socket.session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package ywgz_bzb_pms;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.channels.NotYetConnectedException;
import org.java_websocket.WebSocket.READYSTATE;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.handshake.ServerHandshake;
public class Client {
public static WebSocketClient client;
public static void main(String[] args) throws URISyntaxException, NotYetConnectedException, UnsupportedEncodingException, InterruptedException {
client = new WebSocketClient(new URI("ws://127.0.0.1:8080/WebSocket/pms/chatSocket?username=113195"),new Draft_17()) {
@Override
public void onOpen(ServerHandshake arg0) {
System.out.println("打开链接");
}
@Override
public void onMessage(String arg0) {
System.out.println("收到消息:"+arg0);
}
@Override
public void onError(Exception arg0) {
arg0.printStackTrace();
System.out.println("发生错误已关闭");
}
@Override
public void onClose(int arg0, String arg1, boolean arg2) {
System.out.println("链接已关闭");
}
@Override
public void onMessage(ByteBuffer bytes) {
try {
System.out.println(new String(bytes.array(),"utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
};
client.connect();
while(!client.getReadyState().equals(READYSTATE.OPEN)){
System.out.println("还没有打开");
Thread.sleep(500);
}
System.out.println("打开了");
client.send("{msg:\"999999999999999999\",type:\"1\"}"); //群推
// client.send("{to:\"789789\",msg:\"999999999999999999\",type:\"2\"}"); // type 1是群推 2是单推 为2的时候 必须有 to 给谁推
}
}