WebSocket是什么
Websocket是html5提出的一个协议规范。websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器(webserver)之间能建立一个类似tcp的连接,从而方便通信。在websocket出现之前,web交互一般是基于http协议的短连接或者长连接。
WebSocket是为解决客户端与服务端实时通信而产生的技术。websocket协议本质上是一个基于tcp的协议,是先通过HTTP/HTTPS协议发起一条特殊的http请求进行握手后创建一个用于交换数据的TCP连接,此后服务端与客户端通过此TCP连接进行实时通信。
注意:此时不再需要原HTTP协议的参与了。
传统HTTP客户端与服务器请求响应模式:
v2-c99efde0caccb49814ea83c126b0e18a_hd.jpg
WebSocket请求响应模式:
v2-e4128e588c6c21216319351ee7eb0bac_hd.jpg
WebSocket使用方法
服务器端实例代码:
方法一:注解形式
@ServerEndpoint("/wstest")
public class Test1EndPoint {
//关闭时调用
@OnClose
public void out(Session session, CloseReason closeReason) {
}
//连接时调用
@OnOpen
public void onOpen(Session session, EndpointConfig config) {
}
//接收信息时调用
@OnMessage
public void onMessage(String message, Session session) {
}
//发生错误调用
@OnError
public void onError(Session session, Throwable thr) {
}
}
如果是Spring 框架中引用,屏蔽掉过滤器。
如果找不到此注解:@ServerEndpoint,那么在pom文件中加入以下代码拉取相关包即可。
javax
javaee-api
7.0
provided
方法二继承Endpoint形式
实例代码:
public class EndpointText extends Endpoint implements MessageHandler.Partial, MessageHandler.Whole{
@Override
public void onOpen(Session session, EndpointConfig endpointConfig) {
System.out.println("Endpoint Text");
session.addMessageHandler(this);
try {
session.getBasicRemote().sendText("你好,客户端!");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onClose(Session session, CloseReason closeReason) {
super.onClose(session, closeReason);
System.out.println("已关闭");
}
@Override
public void onError(Session session, Throwable thr) {
super.onError(session, thr);
System.out.println("已出错");
}
@Override
public void onMessage(String s, boolean b) {
System.out.println(s);
}
@Override
public void onMessage(String s) {
System.out.println(s);
}
}
还没结束,需要配置url。首先继承ServerApplicationConfig,需要说明的是
ServerApplicationConfig实现类是在tomcat启动时被加载的(自动扫描,不需要任何配置),其中两个方法分别管理注解和实现类。实例代码:
public class WebsocketConfig implements ServerApplicationConfig{
@Override
public Set getEndpointConfigs(Set> scanned) {
Set result = new HashSet();
if (scanned.contains(EndpointText.class)) {
result.add(ServerEndpointConfig.Builder.create(EndpointText.class, "/text_").build());
}
return result;
}
@Override
public Set> getAnnotatedEndpointClasses(Set> scanned) {
Set> result = new HashSet>();
// Filter out all others to avoid issues when running; if all the annotated endpoints are used, delete this class.
for (Class> clazz : scanned) {
if (clazz.getPackage().getName().startsWith("com.socket")) {
result.add(clazz);
}
}
return result;
}
}
到此服务端结束。
Android客户端使用
注意:客户端使用WebSocket时,url是以ws开头,而不是http。例如:ws://121.40.165.18:8088
我选用的是:java-webSocket
实例代码:
private String address = "ws://192.168.250.38:8181/";
private URI uri;
private static final String TAG = "JavaWebSocket";
public void initSockect() {
try {
uri = new URI(address);
} catch (URISyntaxException e) {
e.printStackTrace();
}
if (null == mWebSocketClient) {
mWebSocketClient = new WebSocketClient(uri) {
@Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i(TAG, "onOpen: ");
}
@Override
public void onMessage(String s) {
Log.i(TAG, "onMessage: " + s);
}
@Override
public void onClose(int i, String s, boolean b) {
Log.i(TAG, "onClose: ");
}
@Override
public void onError(Exception e) {
Log.i(TAG, "onError: ");
}
};
mWebSocketClient.connect();
}
}
这里配上一副图简单理解一下
手动封装WebSocket请求协议
Socket实现WebSocket通讯基础代码。
@Test
public void addition_isCorrect() throws Exception {
Socket socket = new Socket("127.0.0.1", 8080);
StringBuffer sb = new StringBuffer("GET /text HTTP/1.1\r\n");
// 以下为请求头
sb.append("Host:127.0.0.1:8080\r\n");
sb.append("Connection:Upgrade\n");
sb.append("Origin:null\n");
sb.append("Sec-WebSocket-Extensions:x-webkit-deflate-frame\n");
sb.append("Sec-WebSocket-Key:puVOuWb7rel6z2AVZBKnfw==\n");
sb.append("Sec-WebSocket-Version:13\n");
sb.append("Upgrade:websocket\n");
// 注意这里要换行结束请求头
sb.append("\r\n");
System.out.println(sb.toString());
OutputStream os = socket.getOutputStream();
os.write(sb.toString().getBytes());
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int len = -1;
PrintWriter writer = new PrintWriter(os);
while ((len = is.read(bytes)) != -1) {
/**
* 根据WebSocket协议处理信息,并扩展自己的需求
*/
}
socket.close();
}
结束。
笔者能力有限,不足之处欢迎指出。