Golang使用Quic-Go开源库实现Quic客户端和服务端

2024-08-30 03:04

本文主要是介绍Golang使用Quic-Go开源库实现Quic客户端和服务端,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Quic-Go介绍

Quic-Go是Go语言Quic协议(RFC 9000、RFC 9001、RFC 9002)的实现。它支持HTTP/3(RFC 9114),包括QPACK(RFC 9204)和HTTP数据报(RFC 9297)。

  • Github地址

https://github.com/quic-go/quic-go

  • 下载Quic-Go开源库
go get -u github.com/quic-go/quic-go
  • 下述代码中Go版本和Quic-Go版本
  1. go version go1.22.6 linux/amd64
  2. github.com/quic-go/quic-go v0.46.0

Quic客户端代码

package mainimport ("context""crypto/tls""fmt""log""strconv""time""github.com/quic-go/quic-go"
)const addr = "192.168.8.48:19940"func main() {tlsConf := &tls.Config{InsecureSkipVerify: true,NextProtos:         []string{"HLD"},}conn, err := quic.DialAddr(context.Background(), addr, tlsConf, nil)if err != nil {log.Fatalf("Error dialing address: %v", err)}defer conn.CloseWithError(0, "")stream, err := conn.OpenStreamSync(context.Background())if err != nil {log.Fatalf("Error opening stream: %v", err)}defer stream.Close()// 发送数据var sendFlag int = 0go func() {for {sendFlag++sendBuffer := make([]byte, 1024)numberStr := "HLD_" + strconv.Itoa(sendFlag)copy(sendBuffer, numberStr)log.Printf("Send: %v", string(sendBuffer))err = sendData(stream, sendBuffer[:len(numberStr)])if err != nil {fmt.Errorf("Error writing to stream: %v", err)break}time.Sleep(1 * time.Second)}}()// 接收数据go func() {for {recvBuffer := make([]byte, 1024)recvBuffer, err = receiveData(stream, len(recvBuffer))if err != nil {fmt.Errorf("Error reading from stream: %v", err)break}log.Printf("Recv: %v", string(recvBuffer))}}()for {time.Sleep(10 * time.Second)}fmt.Println("Echo test successful")
}func sendData(stream quic.Stream, data []byte) error {_, err := stream.Write(data)if err != nil {return fmt.Errorf("error writing to stream: %w", err)}return nil
}func receiveData(stream quic.Stream, expectedLen int) ([]byte, error) {readBuf := make([]byte, expectedLen)//readPos := 0//for readPos < expectedLen {//	n, err := stream.Read(readBuf[readPos:])//	if err != nil {//		return nil, fmt.Errorf("error reading from stream: %w", err)//	}//	readPos += n//}//return readBuf[:readPos], niln, err := stream.Read(readBuf)if err != nil {return nil, fmt.Errorf("error reading from stream: %w", err)}log.Printf("recvLen: %d\n", n)return readBuf[:n], nil//n, err := io.ReadFull(stream, readBuf)//if err != nil {//	return nil, fmt.Errorf("error reading from stream: %w", err)//}//return readBuf[:n], nil
}

Quic服务端代码

package mainimport ("context""crypto/rand""crypto/rsa""crypto/tls""crypto/x509""encoding/pem""fmt""log""math/big""github.com/quic-go/quic-go"
)// go env -w GO111MODULE=on
// go get -u github.com/quic-go/quic-go
// go list -m github.com/quic-go/quic-goconst addr = "192.168.8.48:19940"func main() {quicConf := &quic.Config{InitialStreamReceiveWindow:     1 << 20,  // 1 MBMaxStreamReceiveWindow:         6 << 20,  // 6 MBInitialConnectionReceiveWindow: 2 << 20,  // 2 MBMaxConnectionReceiveWindow:     12 << 20, // 12 MB}listener, err := quic.ListenAddr(addr, generateTLSConfig(), quicConf)if err != nil {log.Fatalf("Error listening on address: %v", err)}defer listener.Close()for {conn, err := listener.Accept(context.Background())if err != nil {log.Printf("Error accepting connection: %v", err)continue}go handleConnection(conn)fmt.Println("New client connected")}
}func handleConnection(conn quic.Connection) {for {// 接收数据流stream, err := conn.AcceptStream(context.Background())if err != nil {log.Printf("Error accepting stream: %v", err)return}remoteAddr := conn.RemoteAddr().String()fmt.Printf("Client connected from: %s\n", remoteAddr)go func() {defer stream.Close()for {data := make([]byte, 1024)nr, err := stream.Read(data)if err != nil {log.Printf("Error reading from stream: %v", err)return}log.Printf("Recv: %v\n", string(data))nw, err := stream.Write(data[:nr])if err != nil {log.Printf("Error writing to stream: %v", err)return}log.Printf("Send: %v, size: %d\n", string(data[:nr]), nw)}}()}
}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{"HLD"},}
}

Wireshark抓取Quic数据包

在这里插入图片描述

这篇关于Golang使用Quic-Go开源库实现Quic客户端和服务端的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1119614

相关文章

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

gitlab安装及邮箱配置和常用使用方式

《gitlab安装及邮箱配置和常用使用方式》:本文主要介绍gitlab安装及邮箱配置和常用使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装GitLab2.配置GitLab邮件服务3.GitLab的账号注册邮箱验证及其分组4.gitlab分支和标签的

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

在Windows上使用qemu安装ubuntu24.04服务器的详细指南

《在Windows上使用qemu安装ubuntu24.04服务器的详细指南》本文介绍了在Windows上使用QEMU安装Ubuntu24.04的全流程:安装QEMU、准备ISO镜像、创建虚拟磁盘、配置... 目录1. 安装QEMU环境2. 准备Ubuntu 24.04镜像3. 启动QEMU安装Ubuntu4

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4