tinyws

package module
v0.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 11, 2022 License: Apache-2.0 Imports: 23 Imported by: 0

README

简介

tinyws是一个极简的websocket库, 总代码量控制在3k行以下.

Go codecov Go Report Card

特性

  • 3倍的简单
  • 实现rfc6455
  • 实现rfc7692

内容

Installation

go get github.com/antlabs/tinyws

example

客户端连服务端

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"time"

	"github.com/antlabs/tinyws"
)

func main() {
	h1 := func(w http.ResponseWriter, r *http.Request) {
		c, err := tinyws.Upgrade(w, r)
		if err != nil {
			fmt.Println("Upgrade fail:", err)
			return
		}
		defer c.Close()

		for {
			all, op, err := c.ReadTimeout(3 * time.Second)
			if err != nil {
				if err != io.EOF {
					fmt.Println("err = ", err)
				}
				return
			}

			os.Stdout.Write(all)
			c.WriteTimeout(op, all, 3*time.Second)
		}
	}

	http.HandleFunc("/", h1)

	http.ListenAndServe(":12345", nil)
}

服务端接受客户端请求

package main

import (
	"fmt"

	"github.com/antlabs/tinyws"
)

func main() {
	c, err := tinyws.Dial("ws://127.0.0.1:12345/test")
	if err != nil {
		fmt.Printf("err = %v\n", err)
		return
	}

	defer c.Close()

	err = c.WriteMessage(tinyws.Text, []byte("hello"))
	if err != nil {
		fmt.Printf("err = %v\n", err)
		return
	}

	all, _, err := c.ReadMessage()
	if err != nil {
		fmt.Printf("err = %v\n", err)
		return
	}
	fmt.Printf("write :%s\n", string(all))

}

配置函数

客户端配置参数

配置header
func main() {
	tinyws.Dial("ws://127.0.0.1:12345/test", tinyws.WithHTTPHeader(http.Header{
		"h1": "v1",
		"h2":"v2", 
	}))
}
配置握手时的超时时间
func main() {
	tinyws.Dial("ws://127.0.0.1:12345/test", tinyws.WithDialTimeout(2 * time.Second))
}
配置自动回复ping消息
func main() {
	tinyws.Dial("ws://127.0.0.1:12345/test", tinyws.WithReplyPing())
}

服务端配置参数

配置服务自动回复ping消息
func main() {
	c, err := tinyws.Upgrade(w, r, tinyws.WithServerReplyPing())
        if err != nil {
                fmt.Println("Upgrade fail:", err)
                return
        }   
}

Documentation

Overview

TODO 等重写http1.1 解析器, 再把这代码重写下

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrWrongStatusCode      = errors.New("Wrong status code")
	ErrUpgradeFieldValue    = errors.New("The value of the upgrade field is not 'websocket'")
	ErrConnectionFieldValue = errors.New("The value of the connection field is not 'upgrade'")
	ErrSecWebSocketAccept   = errors.New("The value of Sec-WebSocketAaccept field is invalid")

	ErrHostCannotBeEmpty   = errors.New("Host cannot be empty")
	ErrSecWebSocketKey     = errors.New("The value of SEC websocket key field is wrong")
	ErrSecWebSocketVersion = errors.New("The value of SEC websocket version field is wrong, not 13")

	ErrHTTPProtocolNotSupported = errors.New("HTTP protocol not supported")

	ErrOnlyGETSupported     = errors.New("error:Only get methods are supported")
	ErrMaxControlFrameSize  = errors.New("error:max control frame size > 125")
	ErrRsv123               = errors.New("error:rsv1 or rsv2 or rsv3 has a value")
	ErrOpcode               = errors.New("error:wrong opcode")
	ErrNOTBeFragmented      = errors.New("error:since control message MUST NOT be fragmented")
	ErrFrameOpcode          = errors.New("error:since all data frames after the initial data frame must have opcode 0.")
	ErrTextNotUTF8          = errors.New("error:text is not utf8 data")
	ErrClosePayloadTooSmall = errors.New("error:close payload too small")
	ErrCloseValue           = errors.New("error:close value is wrong") //close值不对
	ErrEmptyClose           = errors.New("error:close value is empty") //close的值是空的
	ErrWriteClosed          = errors.New("write close")
)
View Source
var ErrClose = "websocket"
View Source
var ErrFramePayloadLength = errors.New("error frame payload length")
View Source
var (
	ErrNotFoundHijacker = errors.New("not found Hijacker")
)

Functions

func GetNoPortExists

func GetNoPortExists() string

获取没有绑定服务的端口

func StringToBytes

func StringToBytes(s string) (b []byte)

StringToBytes 没有内存开销的转换

Types

type CloseErrMsg

type CloseErrMsg struct {
	Code StatusCode
	Msg  string
}

func (CloseErrMsg) Error

func (c CloseErrMsg) Error() string

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

func Dial

func Dial(rawUrl string, opts ...Option) (*Conn, error)

https://datatracker.ietf.org/doc/html/rfc6455#section-4.1 又是一顿if else, 咬文嚼字

func Upgrade

func Upgrade(w http.ResponseWriter, r *http.Request, opts ...ServerOption) (c *Conn, err error)

func (*Conn) Close

func (c *Conn) Close() error

func (*Conn) ReadJSONTimeout added in v0.0.5

func (c *Conn) ReadJSONTimeout(v interface{}, t time.Duration) (op Opcode, err error)

从websocket读取json

func (*Conn) ReadMessage

func (c *Conn) ReadMessage() (all []byte, op Opcode, err error)

func (*Conn) ReadTimeout

func (c *Conn) ReadTimeout(t time.Duration) (all []byte, op Opcode, err error)

func (*Conn) WriteCloseTimeout added in v0.0.4

func (c *Conn) WriteCloseTimeout(sc StatusCode, t time.Duration) (err error)

func (*Conn) WriteJSONTimeout added in v0.0.5

func (c *Conn) WriteJSONTimeout(op Opcode, v interface{}, t time.Duration) (err error)

写入json至websocket连接

func (*Conn) WriteMessage

func (c *Conn) WriteMessage(op Opcode, data []byte) (err error)

func (*Conn) WriteTimeout

func (c *Conn) WriteTimeout(op Opcode, data []byte, t time.Duration) (err error)

type ConnOption

type ConnOption struct {
	// contains filtered or unexported fields
}

type DialOption

type DialOption struct {
	Header http.Header
	// contains filtered or unexported fields
}

func (*DialOption) Dial

func (d *DialOption) Dial() (c *Conn, err error)

type Opcode

type Opcode uint8
const (
	Continuation Opcode = iota
	Text
	Binary

	Close
	Ping
	Pong
)

func (Opcode) String

func (c Opcode) String() string

type Option

type Option interface {
	// contains filtered or unexported methods
}

func WithCompression

func WithCompression() Option

配置压缩

func WithDecompressAndCompress added in v0.0.3

func WithDecompressAndCompress() Option

配置压缩和解压缩

func WithDecompression added in v0.0.2

func WithDecompression() Option

配置解压缩

func WithDialTimeout

func WithDialTimeout(t time.Duration) Option

配置握手时的timeout

func WithHTTPHeader

func WithHTTPHeader(h http.Header) Option

配置http.Header

func WithReplyPing

func WithReplyPing() Option

配置自动回应ping frame, 当收到ping, 回一个pong

func WithTLSConfig

func WithTLSConfig(tls *tls.Config) Option

配置tls.config

type ServerOption

type ServerOption interface {
	// contains filtered or unexported methods
}

func WithServerDecompressAndCompress added in v0.0.3

func WithServerDecompressAndCompress() ServerOption

配置压缩和解压缩

func WithServerDecompression added in v0.0.2

func WithServerDecompression() ServerOption

配置解压缩

func WithServerIgnorePong added in v0.0.3

func WithServerIgnorePong() ServerOption

配置忽略pong消息

func WithServerReplyPing

func WithServerReplyPing() ServerOption

配置自动回应ping frame, 当收到ping, 回一个pong

type StatusCode

type StatusCode int16

https://datatracker.ietf.org/doc/html/rfc6455#section-7.4.1 这里记录了各种状态码的含义

const (
	// NormalClosure 正常关闭
	NormalClosure StatusCode = 1000
	// EndpointGoingAway 对端正在消失
	EndpointGoingAway StatusCode = 1001
	// ProtocolError 表示对端由于协议错误正在终止连接
	ProtocolError StatusCode = 1002
	// DataCannotAccept 收到一个不能接受的数据类型
	DataCannotAccept StatusCode = 1003
	// NotConsistentMessageType 表示对端正在终止连接, 消息类型不一致
	NotConsistentMessageType StatusCode = 1007
	// TerminatingConnection 表示对端正在终止连接, 没有好用的错误, 可以用这个错误码表示
	TerminatingConnection StatusCode = 1008
	// TooBigMessage  消息太大, 不能处理, 关闭连接
	TooBigMessage StatusCode = 1009
	// NoExtensions 只用于客户端, 服务端返回扩展消息
	NoExtensions StatusCode = 1010
	// ServerTerminating 服务端遇到意外情况, 中止请求
	ServerTerminating StatusCode = 1011
)

func (StatusCode) String

func (s StatusCode) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL