Skip to content

Latest commit

 

History

History
140 lines (94 loc) · 5.17 KB

README_zh.md

File metadata and controls

140 lines (94 loc) · 5.17 KB

WebSocket example

WebSocket 是一种支持客户端与服务器在单个 TCP 连接上进行全双工通信的应用层通信协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,它允许服务端主动向客户端推送数据(HTTP 的通信只能由客户端发起)。在 WebSocket API 中,浏览器和服务器只需要一次握手,两者之间就可以创建持久性连接,并进行双向数据传输。

本项目提供了基于 Spring Boot 的 WebSocket 服务器端,基于 SockJS+STOMP 的浏览器端和基于 StompProtocolAndroid 的安卓客户端。

简单使用

服务器端目前有三个接收消息的端点:

  1. /broadcast

该接口会转发它接收到的所有消息到 /b 端点的订阅者。

  1. /group/{groupID}

这个端点用于模拟群组。举个例子,一个客户端发送消息给 /group/1,所有订阅了端点 /g/1 的客户端都会接收到消息。如果要改变接收消息的端点,需要同时改变 ControllerWebSocketConfig 的相关代码。

  1. /chat

/chat 是用于点对点通信,用与模拟私聊。如果 Alice(userID 为 1)想和 Bob(userID 为 2)聊天,她需要发送消息到 /chat,并且在请求体中附带相关信息(json 化的 ChatMessage):

// js code
function sendMessage() {
    var message = $('#message').val();
    stompClient.send('/chat', {}, JSON.stringify({
        'userID': 2, 
        'fromUserID': 1, 
        'message': "Hello Bob"})
    );
}

userID 是必须的,这个属性会被服务端用来判断转发的端点:

simpMessagingTemplate.convertAndSendToUser(String.valueOf(chatMessage.getUserID()), "/msg", response);

通过以上的代码,Alice 的消息会被转发到 /user/2/msg 的订阅者。如果 Bob 订阅了他自己对应的端点,他将收到消息。

如果 Alice 也想收到发给她的消息,她也应当订阅她自己(本例中 Alice 应该订阅 /user/1/msg):

stompClient.subscribe('/user/' + 1 + '/msg', function (response) {
    showResponse(JSON.parse(response.body).responseMessage);
});

这样,当 Bob 给 Alice 发送消息的时候,Alice 会成功收到。

Token 身份认证

有时候,我们会希望我们的端点只供认证的用户使用,所以我们需要检查用户的身份。常用的做法是通过 Header 传递 Token,WebSocket 协议也支持与 HTTP 类似的 Header。

下面是一个通过 Header 传递 token 并验证的示例。

服务器端,我们需要在 controller 中端点方法中通过注解接收相应的 Header:

private String token = "this is a token generated by your code!";

@MessageMapping("/broadcast")
@SendTo("/b")
public Response say(Message message, @Header(value = "authorization") String authorizationToken) {
    if (authorizationToken.equals(token)) {
        System.out.println("Token check success!!!");
    } else {
        System.out.println("Token check failed!!!");
    }
    return new Response("Welcome, " + message.getName() + "!");
}

当通过客户端 STOMP 的 SEND 方法向服务器发送消息并附带 authorization header 的时候,authorization 的值(即 token)会被服务器成功获取。

浏览器端,我们需要做的是在 SEND 方法中附带 HTTP Header:

stompClient.send(
    '/broadcast',
    {
        "authorization": "this is a token generated by your code!"
    },
    JSON.stringify({'name': name})
);

现在,当我们向 /broadcast 发送消息的时候,authorization 也会被发送给服务器。

安卓端,跟浏览器端大体类似:

String token = "this is a token generated by your code!";
StompHeader authorizationHeader = new StompHeader("authorization", token);
stompClient.send(new StompMessage(
        // STOMP 指令
        StompCommand.SEND,
        // STOMP headers
        // 第一个 header 是必须的,其他的我们可以自定义
        Arrays.asList(new StompHeader(StompHeader.DESTINATION, Const.broadcast), authorizationHeader),
        // STOMP 荷载(即消息体)
        jsonObject.toString())
    ).subscribe(...);

现在,我们可以在服务器生成 Token,并且在用户成功登录的时候发送给用户。当用户想要发送消息到端点时,需要先提供合法的 Token。

服务器端构建

spring boot starter

Broadcast(Browser)

broadcast in browser

Broadcast(Android)

broadcast in android

Dynamic Groups(Browser)

group in browser

Dynamic Groups(Android)

group in android

Point-to-Point Chat(Browser)

chat in browser

Point-to-Point Chat(Android)

chat in browser

LICENSE

MIT