当前位置: 首页 > news >正文

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数据包

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 企业数据治理之主数据---供应商主数据
  • Java核心API——io类缓冲流
  • 什么是杨氏模量
  • 22AP10 SS524 平替 海思HI3521DV200 可提供开发资料
  • IP-RDS-222、IP-PRZ-59-AM12、EG-TRZ-42-L、EG-TRZ-42-H比例减压阀放大器
  • Qt详解QHostInfo
  • 【python报错已解决】AttributeError: module ‘PIL.Image‘ has no attribute ‘ANTIALIAS‘
  • 对标GPT4o,智谱推出新一代基座大模型 GLM-4-Plus
  • JDBC和Mybatis中的批处理
  • 【Python数据分析】numpy中的npz和npy的用法和区别
  • scrapy框架--快速了解
  • 队列算法【基于顺序表的环形队列】
  • VMware安装Ubuntu 23.10.1系统图文版
  • 【小白深度学习入门】【1】卷积神经网络CNN 结构、基本原理以及常见问题详解
  • 前端 数值列 禁止输入多个小数点
  • @angular/forms 源码解析之双向绑定
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • android 一些 utils
  • Javascript编码规范
  • Java读取Properties文件的六种方法
  • Kibana配置logstash,报表一体化
  • leetcode-27. Remove Element
  • Map集合、散列表、红黑树介绍
  • node.js
  • SAP云平台里Global Account和Sub Account的关系
  • Unix命令
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 闭包--闭包作用之保存(一)
  • 编写符合Python风格的对象
  • 基于组件的设计工作流与界面抽象
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 双管齐下,VMware的容器新战略
  • 无服务器化是企业 IT 架构的未来吗?
  • 系统认识JavaScript正则表达式
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • Hibernate主键生成策略及选择
  • mysql面试题分组并合并列
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​io --- 处理流的核心工具​
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​批处理文件中的errorlevel用法
  • # Kafka_深入探秘者(2):kafka 生产者
  • $(function(){})与(function($){....})(jQuery)的区别
  • (1)(1.13) SiK无线电高级配置(六)
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (补)B+树一些思想
  • (纯JS)图片裁剪
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)