zoukankan      html  css  js  c++  java
  • go语言编程之旅笔记4

    第四章: websocket服务

    1. 简介

      我写笔记的目的是为了记录所用到的一些组件,但是从这章开始到结束组件不像前面多了。

      ws可在单个tcp连接上建立全双工通讯,允许服务端主动向客户端输出。保持连接状态,是一种有状态的应用层协议。建立方式通过可以http代理来握手,使用HTTP Upgrade头进行协议升级。

    2. 库选择

      书上写了多种库,包括nhooyr.io/websocket和gorilla/wesocket等,后者成熟功能多,前者更符合go的习惯并且有并发,完整关闭,可以编译为wasm等好处。

      go get -u nhooyr.io/websocket
      
    3. 基本用法

      server.go
      package main
      
      import (
      	"context"
      	"fmt"
      	"log"
      	"net/http"
      	"time"
      
      	"nhooyr.io/websocket"
      	"nhooyr.io/websocket/wsjson"
      )
      
      func main() {
      	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
      		fmt.Fprintln(w, "HTTP Hello")
      	})
      
      	http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
      		conn, err := websocket.Accept(w, r, nil)
      		if err != nil {
      			log.Println(err)
      			return
      		}
      		defer conn.Close(websocket.StatusInternalError, "internal error")
      		ctx, cancel := context.WithTimeout(r.Context(), time.Second*10)
      		defer cancel()
      
      		var v interface{}
      		err = wsjson.Read(ctx, conn, &v)
      		if err != nil {
      			log.Println(err)
      			return
      		}
      		log.Printf("client resvered: %v
      ", v)
      
      		err = wsjson.Write(ctx, conn, "Hello websocket client.")
      		if err != nil {
      			log.Println(err)
      			return
      		}
      
      		conn.Close(websocket.StatusNormalClosure, "")
      	})
      
      	log.Fatal(http.ListenAndServe(":2021", nil))
      }
      
      
      client.go
      package main
      
      import (
      	"context"
      	"fmt"
      	"time"
      
      	"nhooyr.io/websocket"
      	"nhooyr.io/websocket/wsjson"
      )
      
      func main() {
      	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
      	defer cancel()
      
      	c, _, err := websocket.Dial(ctx, "ws://localhost:2021/ws", nil)
      	if err != nil {
      		panic(err)
      	}
      	defer c.Close(websocket.StatusInternalError, "internal error")
      	err = wsjson.Write(ctx, c, "Hello websocket server")
      	if err != nil {
      		panic(err)
      	}
      
      	var v interface{}
      	err = wsjson.Read(ctx, c, &v)
      	if err != nil {
      		panic(err)
      	}
      	fmt.Printf("resvered server's response : %v
      ", v)
      	c.Close(websocket.StatusNormalClosure, "")
      }
      
      
      
    4. 其他

      github和博客园都支持不了md的图

      sequenceDiagram
      client->>home/: HTTP / 请求首页
      home/->>client: 聊天室页面
      client->>webscoket: 通过ws协议请求: /ws
      webscoket->>webscoket: 协议转换
      webscoket->>client: 响应
      webscoket->broadcast: channel通信
      webscoket->client: 通过ws长连接发送消息
      

      代码没有特别的,不仔细贴了,基本就是channel的操作,完整的还是去github。

      一段单例的代码,双检锁基本都长这样,不过没有看到‘易变’。golang有没有这个东西我不记得了
      package singleton
      
      import "sync"
      
      type singleton2 struct {
      	count int
      }
      
      var (
      	instance2 *singleton2
      	mutex     sync.Mutex
      )
      
      func New() *singleton2 {
      	if instance2 == nil {
      		mutex.Lock()
      		if instance2 == nil {
      			instance2 = new(singleton2)
      		}
      		mutex.Unlock()
      	}
      	return instance2
      }
      func (s *singleton2) Add() int {
      	s.count++
      	return s.count
      }
      
      

      在敏感词处理环节介绍了DFA和贝叶斯分类算法,提到了两个库

      go get -u github.com/antlinker/go-dirtytilter
      go get -u github.com/jbrukh/bayesian
      

      用户识别用的token生成方式和之前章节一样,离线消息处理使用了内置的container/ring环形链表

  • 相关阅读:
    JSP内置对象
    java 中list还有array的区别
    js动态修改界面碰见的疑惑
    购物多条件商品查询逻辑处理
    数据库信息备份
    关于毕设的一些小问题
    在<a></a>标签中正确调用javaScript脚本
    oracle实训0705经验
    第十五天学习进度--数列找规律算法(预测算法)(1)
    第十四天学习进度--相关系数和显著水平
  • 原文地址:https://www.cnblogs.com/suzu/p/13907237.html
Copyright © 2011-2022 走看看