Https+Websocket+Nginx+Beego不得不说的那些事

前言

上一篇我们说了beego和websocket的具体用户,那么项目在改为https后,发现前端和后端无法连接的问题
具体包含 nginx的使用、前端ws调整、beego代码调整等几个坑。

Nginx配置路由转发和证书

以下是nginx配置Https信息,需要提前将两个证书文件放到nginx/conf/目录下。
配置好后nginx/sbin/nginx -s reload 重新加载。

server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      ***.org.pem;
        ssl_certificate_key  ***.org.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;	# 这里后端websocket与前端连接5分钟后超时断开。

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location /ws{					# 这里与前端js里路一定要配对一样。
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_redirect off;
            proxy_read_timeout 120;
            proxy_pass http://0.0.0.0:8080/ws;
        }

       location / {
            try_files /_not_exists_ @backend;
        }
		location @backend{
            proxy_pass http://127.0.0.1:8080;  # 这里为本服务器程序端口
        }
 }

前端代码

var ws = new WebSocket('ws://IP:8080/ws');
改为
var ws = new WebSocket('wss://证书所对应的域名/ws');

beego中代码

以下代码是controller核心部分代码,router等代码则不展示。

package controllers
import (
    "fmt"
    "github.com/astaxie/beego"
    "net/http"
    "github.com/gorilla/websocket"
)

type MySocketController struct {
    beego.Controller
}

// 以下这句话必须加,不然还是连不上
var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool {
    return true
},}

// 定义数据结构{"表格id1": {客户端浏览器id: true}, "表格id2": {客户端浏览器id: true}}
var tableClinets = make(map[string]map[*websocket.Conn]bool)

func (c *MySocketController) Get() {
    ws, err := upgrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
    if err != nil{
        beego.Info(err)
    }
    defer ws.CloseHandler()
    
	// 这里是我用户的结构体,你可以按自己需要定义
    var msg models.RecvWs
    
    for {
        err := ws.ReadJSON(&msg)
        if err != nil {
            beego.Info("页面可能断开啦")
            for k,v := range tableClinets{
                if _,ok := v[ws];ok{
                    delete(v, ws)
                    if len(v) == 0{
                        delete(tableClinets,k)
                    }
                    fmt.Println(tableClinets)
                }
            }
            break
        }
     
        // 获取表格ID,判断是否存在数据结构中,不存在插入。
        tableId := msg.TableUuid
        if sockets, ok := tableClinets[tableId]; ok{
            if _, ok := sockets[ws]; !ok{
                sockets[ws] = true
            }
        }else{
			client_map := map[*websocket.Conn]bool{ws: true}
            tableClinets[tableId] = client_map
        }

        // 将获取的消息按表格ID广播出去
        clients := tableClinets[tableId]
        go func(msg models.RecvWs){
            // 开启协程去做一些操作,例如可以实时去修改库里的内容
        }(msg)
        
        // 将消息广播的同时要把自己的客户端除去,自己不能给自己广播。
		for client := range clients{
            if client != ws{
                err = client.WriteJSON(msg)
                if err != nil {
                    client.Close()
                    delete(clients, client)
                    if len(clients) == 0{
                        delete(tableClinets,msg.TableUuid)
                    }
                }
            }
        }
    }
}

好的,我可以为您详细明一下stomp+websocket+springboot的实现方式。 首先,stomp是基于WebSocket协议的一种消息传输协议。它提供了一种简单的方式来实现消息传输,使得客户端和服务器之间可以通过WebSocket进行双向通信。而Spring Boot是一个快速开发Web应用程序的框架,它提供了对WebSocket和STOMP的内置支持,使得我们可以轻松地实现基于WebSocket和STOMP的应用程序。 下面是stomp+websocket+springboot的实现步骤: 1. 添加依赖 首先,在Spring Boot项目中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ``` 2. 配置WebSocket 在Spring Boot项目中,我们需要配置WebSocket。我们可以创建一个WebSocketConfig类,用来配置WebSocket相关的参数。在WebSocketConfig类中,我们需要覆盖registerStompEndpoints方法,该方法用于注册一个或多个STOMP端点,以便客户端可以连接到我们的WebSocket服务器。 ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/websocket").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } } ``` 在上面的代码中,我们注册了一个名为“/websocket”的STOMP端点,并启用了SockJS协议。这意味着我们的应用程序将支持基于WebSocket的连接,以及使用SockJS的WebSocket连接。 3. 消息处理 在WebSocketConfig类中,我们还需要配置消息处理。我们可以使用@MessageMapping注解来处理从客户端发送的消息,@SendTo注解将处理结果发送回客户端。例如: ```java @Controller public class WebSocketController { @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(HelloMessage message) throws Exception { Thread.sleep(1000); return new Greeting("Hello, " + message.getName() + "!"); } } ``` 在上面的代码中,我们定义了一个名为“/hello”的消息映射,该映射将处理从客户端发送的消息。我们使用@SendTo注解将处理结果发送回客户端。 4. 客户端代码 最后,我们需要编写客户端代码来连接WebSocket服务器,并发送和接收消息。我们可以使用JavaScript或Java等语言编写客户端代码。以下是一个使用JavaScript编写的简单客户端代码示例: ```javascript var stompClient = null; function connect() { var socket = new SockJS('/websocket'); stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { console.log('Connected: ' + frame); stompClient.subscribe('/topic/greetings', function (greeting) { showGreeting(JSON.parse(greeting.body).content); }); }); } function sendName() { var name = document.getElementById('name').value; stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name })); } function showGreeting(message) { var p = document.createElement('p'); p.appendChild(document.createTextNode(message)); document.getElementById('greetings').appendChild(p); } ``` 在上面的代码中,我们使用SockJS和Stomp.js库来连接WebSocket服务器,并发送和接收消息。我们使用subscribe方法来订阅指定的STOMP端点,并使用send方法来发送消息。 总结 以上就是stomp+websocket+springboot的实现方式。通过以上步骤,我们可以轻松地实现基于WebSocket和STOMP的应用程序,实现客户端和服务器之间的双向通信。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值