webrtc远程控制系统源码学习笔记_服务端(二)

webrtc远程控制系统源码学习笔记_服务端(二)

1、server.go

//收到Answer时事件处理,与设备端建立websocket连接
func AnswerHandler(c *gin.Context) {
	ws, err := upgrader.Upgrade(c.Writer, c.Request, nil) //将get请求升级为websocket协议
	if err != nil {
		return
	}

	var client *Client
    //接收来自设备端的websocket连接请求,使得设备上线
	for {
		req := &Session{}
		if err := ws.ReadJSON(req); err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure, websocket.CloseNoStatusReceived) {
				fmt.Printf("error: %v", err)
			}
			return
		}

		if req.Type == "online" {
			if h.ExistClient(req.DeviceId) {
				resp := Session{}
				resp.Type = "error"
				resp.Msg = req.DeviceId + " is exist"
				err = ws.WriteJSON(resp)
				continue
			}

			client = h.NewClient(req.DeviceId, ws) //将设备添加到hub中
            //设置连接超时事件处理,如果一定时间没有收到设备端的心跳包,服务端就会断开WebSocket连接
			client.conn.SetCloseHandler(func(code int, text string) error {
				h.Close(req.DeviceId)  //在hub中删除设备
				fmt.Println(req.DeviceId, " is offline,")
				return nil
			})

			break
		}
	}
    //此时设备端只是与服务器建立了websocket连接
    //下面服务器就可以转发来自客户端和设备端的信息
	go client.readPump()  //开启线程,接收来自设备端的请求,并放入channel
	go client.writePump()//开启线程,将客户端的信息转发给设备端,直到建立 RTC 连接
}

在这里插入图片描述

//收到offer时事件处理,与客户端建立websocket连接
func OfferHandler(c *gin.Context) {
	ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)  //将get请求升级为websocket协议
	if err != nil {
		return
	}

	client := NewClient(ws)//为客户端创建一个client
    //接收来自客户端想要连接到某个设备的请求
	for {
		req := &Session{}
		if err := ws.ReadJSON(req); err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure, websocket.CloseNoStatusReceived) {
				fmt.Printf("error: %v", err)
			}
			return
		}
        //服务端接收到客户端offer请求后首先会检查当前设备是否存在以及可用,如果不可用,返回错误
        //如果可用则会将客户端Clinet的receive_ch与设备端的send_ch连接在一起
        //同理也将客户端的send_ch与设备端的receive_ch连接在一起
		if req.Type == "offer" {
			if h.ExistClient(req.DeviceId) {
				if h.client[req.DeviceId].using {
					resp := Session{}
					resp.Type = "error"
					resp.Msg = req.DeviceId + " is using"

					if err := ws.WriteJSON(resp); err != nil {
						fmt.Println(err)
						return
					}
					continue
				}

				h.Connection(req.DeviceId, client)//连接设备端与客户端的client
                //连接超时处理
				client.conn.SetCloseHandler(func(code int, text string) error {
					h.Close(req.DeviceId)
					return nil
				})

				msg, _ := json.Marshal(req)  //将req转换为json格式
				client.send_ch <- string(msg)//将连接请求放入client.send_ch,以便发送给设备端
				data := <-client.receive_ch  //获取client.receive_ch中的数据,即设备端的send_ch
                //将接收到来自设备端的请求发送到服务端
				if err := client.conn.WriteMessage(websocket.TextMessage, []byte(data)); err != nil {
					fmt.Println(err)
					return
				}
				break
			}
		}

		resp := Session{}
		resp.Type = "error"
		resp.Msg = req.DeviceId + " is not exist"
		if err := client.conn.WriteJSON(resp); err != nil {
			fmt.Println(err)
			return
		}
	}
    //此时客户端与设备端都与服务器建立了websocket连接
    //下面两个线程应该是在双方进行密码验证的时候,服务器转发双方的信息
	go client.readPump()  //开启线程,接收来自客户端的请求,并放入channel
	go client.writePump() //开启线程,将设备端的信息转发给客户端,直到建立 RTC 连接

}

2、hub.go

  //创建一个设备端的client,并将之添加到hub
 func (h *hub) NewClient(key string, ws *websocket.Conn) *Client {
	client := &Client{
		conn:       ws,
		receive_ch: make(chan string, 1),
		send_ch:    make(chan string, 1),
		using:      false,
	}
	h.client[key] = client
	return client
}
  //根据设备ID获取它的client
    func (h *hub) GetClient(key string) *Client {
	    return h.client[key]
    }
//检查设备是否存在
func (h *hub) ExistClient(key string) bool {
	if _, ok := h.client[key]; ok {
		return true
	}
	return false
}
//获取所有设备的resq_client
func (h *hub) GetClients() []resp_clients {
	var res []resp_clients

	for k, v := range h.client {
		tmp := resp_clients{
			k,
			v.using,
		}
		res = append(res, tmp)
	}
	return res
}
//将设备从hub中删除
func (h *hub) Close(key string) {
	close(h.client[key].send_ch)
	close(h.client[key].receive_ch)
	delete(h.client, key)
}
//绑定客户端与设备端的client,并设置using字段置为true,防止发生抢占
func (h *hub) Connection(key string, client *Client) {
	client.receive_ch = h.client[key].send_ch
	client.send_ch = h.client[key].receive_ch
	h.client[key].using = true
	client.using = true
}
//创建一个hub
func NewHub() *hub {
	return &hub{
		make(map[string]*Client),
	}
}

3、client.go

//创建一个client
func NewClient(ws *websocket.Conn) *Client {
	client := &Client{
		conn:       ws,
		receive_ch: nil,
		send_ch:    nil,
		using:      false,
	}

	return client
}
//获取websocket传来的请求,并放入client.send_ch
func (c *Client) readPump() {
	defer c.conn.Close()

	for {
		_, msg, err := c.conn.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure, websocket.CloseNoStatusReceived) {
				fmt.Printf("error: %v", err)
			}
			return
		}
		c.send_ch <- string(msg)
	}
}
//发送来自client.receive_ch
func (c *Client) writePump() {
	defer c.conn.Close()

	for data := range c.receive_ch {
		err := c.conn.WriteMessage(websocket.TextMessage, []byte(data))
		if err != nil {
			fmt.Println(err)
			return
		}
	}
	err := c.conn.WriteMessage(websocket.TextMessage, []byte("connection has been closed"))
	if err != nil {
		fmt.Println(err)
		return
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值