QUIC协议试触-节点通信协议参考

从某歌网站了解到,QUIC协议可能会成为未来的HTTP3协议的方向,这是一个使用UDP协议来达到TCP的效果,甚至某些方面更优,但是这家伙是以UDp为基础的,还是会存在UDP的一些不足,比如:安全问题,也就是反射攻击,即伪造原地址;还有就是这些年性能的优化提升都几乎针对 TCP ,使得 UDP 性能没有啥改进。当然随着 QUIC3 的发布,相信后续应该会有相对的投入。

想利用该协议来实现节点间数据通信,顾实验一番,下面有啥错误的地方,一定要指出来哦,感谢大家:

我是使用了这个go库来玩的:github.com/lucas-clemente/quic-go

服务端实现


const saddr = "localhost:9999"

func QUIC_Server_Run() {
    
    
	listener, err := quic.ListenAddr(saddr, generateTLSConfig(), nil)
	if err != nil {
    
    
		fmt.Println(err)
	}
	bg := context.Background()
	cancel, cancelFunc := context.WithCancel(bg)
	defer cancelFunc()
	for {
    
    
		sess, err := listener.Accept(cancel)
		if err != nil {
    
    
			fmt.Println(err)
		} else {
    
    
			fmt.Println(sess)
			go dealSession(cancel, sess)
		}
	}
}
func dealSession(ctx context.Context, sess quic.Session) {
    
    
	stream, err := sess.AcceptStream(ctx)
	if err != nil {
    
    
		panic(err)
	} else {
    
    
		result := bytes.NewBuffer(nil)
		var buf [65542]byte // 由于 标识数据包长度 的只有两个字节 故数据包最大为 2^16+4(魔数)+2(长度标识)
		for {
    
    
			n, err := stream.Read(buf[0:])
			result.Write(buf[0:n])
			if err != nil {
    
    
				if err == io.EOF {
    
    
					panic(errors.New("客户端主动断开连接"))
				} else {
    
    
					//logger.PError(err, "read err:")
					panic(err)
				}
			} else {
    
    
				scanner := bufio.NewScanner(result)
				scanner.Split(codec.PacketSplitFunc)
				for scanner.Scan() {
    
    
					fmt.Printf("Server: Got '%s'\n", string(scanner.Bytes()[6:]))
					_, err = stream.Write(codec.Encode(scanner.Bytes()[6:]).Bytes())
					if err != nil {
    
    
						panic(err)
					}
				}
			}
			result.Reset()
		}
	}
}

// Setup a bare-bones TLS config for the server
func generateTLSConfig() *tls.Config {
    
    
	key, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
    
    
		panic(err)
	}
	template := x509.Certificate{
    
    SerialNumber: big.NewInt(1)}
	certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
	if err != nil {
    
    
		panic(err)
	}
	keyPEM := pem.EncodeToMemory(&pem.Block{
    
    Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
	certPEM := pem.EncodeToMemory(&pem.Block{
    
    Type: "CERTIFICATE", Bytes: certDER})

	tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
	if err != nil {
    
    
		panic(err)
	}
	return &tls.Config{
    
    Certificates: []tls.Certificate{
    
    tlsCert}, NextProtos: []string{
    
    "quic"}}
}

客户端实现

const addr = "localhost:9999"
const message = "ccccccccccccccccccccccd"

func QUIC_Client_run() {
    
    
	session, err := quic.DialAddr(addr, &tls.Config{
    
    InsecureSkipVerify: true, NextProtos: []string{
    
    "quic"}}, nil)
	if err != nil {
    
    
		fmt.Println(err)
		return
	}
	bg := context.Background()
	cancel, cancelFunc := context.WithCancel(bg)
	defer cancelFunc()
	stream, err := session.OpenStreamSync(cancel)
	if err != nil {
    
    
		fmt.Println(err)
		return
	}
	i := 0
	go func() {
    
    
		var data2 [65535]byte
		result := bytes.NewBuffer(nil)
		for {
    
    
			n, err := stream.Read(data2[0:])
			if err != nil {
    
    
				panic(err)
			}
			result.Write(data2[0:n])
			scanner := bufio.NewScanner(result)
			scanner.Split(codec.PacketSplitFunc)
			for scanner.Scan() {
    
    
				fmt.Println(string(scanner.Bytes()[6:]))
			}
		}
	}()
	for {
    
    
		bf := codec.Encode([]byte(message + strconv.Itoa(i)))
		_, err = stream.Write(bf.Bytes())

		if err != nil {
    
    
			fmt.Println(err)
			return
		}
		i++
	}
}

两个处理粘包半包的函数

package codec
const (
	// 包头魔术
	PacketHead uint32 = 0x123456
)

func PacketSplitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
    
    
	// 检查 atEOF 参数 和 数据包头部的四个字节是否 为 0x123456(我们定义的协议的魔数)
	if !atEOF && len(data) > 6 && binary.BigEndian.Uint32(data[:4]) == PacketHead {
    
    
		var l int16
		// 读取 数据包 实际数据的长度(大小为0~2^16)
		err = binary.Read(bytes.NewReader(data[4:6]), binary.BigEndian, &l)
		if err != nil {
    
    
			panic(err)
		}
		pl := int(l) + 6
		if pl <= len(data) {
    
    
			return pl, data[:pl], nil
		}
	}
	return
}

func Encode(data []byte) *bytes.Buffer {
    
    
	magicNum := make([]byte, 4)
	binary.BigEndian.PutUint32(magicNum, 0x123456)
	lenNum := make([]byte, 2)
	binary.BigEndian.PutUint16(lenNum, uint16(len(data)))
	packetBuf := bytes.NewBuffer(magicNum)
	packetBuf.Write(lenNum)
	packetBuf.Write(data)
	return packetBuf
}

测试

不得不说,udp还是一如既往的块
看一下效果,我运行了客户端5秒钟,一下子就传输了5w条数据了
在这里插入图片描述
同样使用tcp协议来测试,发送5s:
在这里插入图片描述

基于UDP的QUIC传输数据效果确实不错;
QUIC 协议的主要目的,是为了整合 TCP 协议的可靠性和 UDP 协议的速度和效率。

猜你喜欢

转载自blog.csdn.net/qq_41257365/article/details/114500436