使用go语言在本地搭建quic服务端与客户端

使用go语言在本地搭建quic服务端与客户端

操作系统:Ubuntu 22.04

环境配置和依赖安装

#安装go语言(需要1.18+版本)
wget https://go.dev/dl/go1.21.4.linux-amd64.tar.gz
#删除旧版本go并解压新版本到系统目录
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.21.4.linux-amd64.tar.gz
#永久配置go语言的环境变量
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc

#安装依赖库
sudo apt update
sudo apt install -y libssl-dev git make gcc wireshark-qt
#若wireshark-qt不存在,改为wireshark也可以

安装quic库

#创建项目目录
mkdir quic-demo && cd quic-demo
go mod init quic-demo

#安装quic库
go get github.com/quic-go/quic-go

#生成TLS证书(QUIC强制要求加密)
openssl req -x509 -newkey rsa:2048 -nodes -keyout server.key -out server.crt -days 365 -subj '/CN=localhost'

生成服务端代码

#创建server.go并进行编辑,我使用如下方法创建
touch server.go
nano server.go
//服务端代码(server.go)
package main

import (
	"context"
	"crypto/rsa"//有可能不需要,注释掉即可
	"crypto/tls"
	"crypto/x509"//有可能不需要,注释掉即可
	"fmt"
	"io"
	"log"
	"os"//有可能不需要,注释掉即可
	"github.com/quic-go/quic-go"
)

func main() {
	// 加载TLS证书
	cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
	if err != nil {
		log.Fatal(err)
	}
    
    // 配置QUIC监听器
    listener, err := quic.ListenAddr(
        "0.0.0.0:4242", 
        &tls.Config{
            Certificates: []tls.Certificate{cert},
            NextProtos:   []string{"quic-demo"},
        },
        nil, // 使用默认QUIC配置
    )
    if err != nil {
        log.Fatal(err)
    }
    defer listener.Close()

    fmt.Println("QUIC Server listening on :4242")

    // 接受客户端连接
    conn, err := listener.Accept(context.Background())
    if err != nil {
        log.Fatal(err)
    }

    // 接受数据流
    stream, err := conn.AcceptStream(context.Background())
    if err != nil {
        log.Fatal(err)
    }

    // 读取客户端消息
    buf := make([]byte, 1024)
    n, err := stream.Read(buf)
    if err != nil && err != io.EOF {
        log.Fatal(err)
    }
    fmt.Printf("Received: %s\n", buf[:n])

    // 发送响应
    _, err = stream.Write([]byte("Hello from QUIC server!"))
    if err != nil {
        log.Fatal(err)
    }
}

生成客户端代码

#创建client.go并进行编辑,我使用如下方法创建
touch client.go
nano client.go
//客户端代码(cilent.go)
package main

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io"
	"log"
	"os"
	"github.com/quic-go/quic-go"
}

func main() {
	// 加载自签名证书
	pool := x509.NewCertPool()
	certData, err := os.ReadFile("server.crt")
	if err != nil {
		log.Fatal(err)
	}
	pool.AppendCertsFromPEM(certData)
    // 配置QUIC连接
    tlsConf := &tls.Config{
        RootCAs:            pool,
        InsecureSkipVerify: true, // 跳过证书验证(仅用于测试)
        NextProtos:         []string{"quic-demo"},
    }

    // 连接到服务器
    conn, err := quic.DialAddr(
        context.Background(),
        "localhost:4242",
        tlsConf,
        nil, // 使用默认QUIC配置
    )
    if err != nil {
        log.Fatal(err)
    }
    defer conn.CloseWithError(0, "")

    // 创建数据流
    stream, err := conn.OpenStreamSync(context.Background())
    if err != nil {
        log.Fatal(err)
    }
    defer stream.Close()

    // 发送消息
    _, err = stream.Write([]byte("Hello from QUIC client!"))
    if err != nil {
        log.Fatal(err)
    }

    // 读取响应
    buf := make([]byte, 1024)
    n, err := stream.Read(buf)
    if err != nil && err != io.EOF {
        log.Fatal(err)
    }
    fmt.Printf("Received: %s\n", buf[:n])
}

编译和运行

#编译时需要添加quic标签
go build -tags quic server.go
go build -tags quic client.go

#设置SSL密钥日志文件路径(必须步骤)
export SSLKEYLOGFILE=~/sslkeylog.log

测试

wireshark设置

  • 在Preferences -> Protocols -> TLS设置(Pre)-Master-Secret log文件名,需要输入sslkeylog.log的完整路径
  • 开始捕获(选择正确的网卡,我是在是本地回环地址lo)

启动服务端

# 第一个终端启动服务端(quic-demo文件下)
sudo ./server

启动客户端

# 第二个终端启动客户端(quic-demo文件下)
#需要保持SSLKEYLOGFILE环境变量
SSLKEYLOGFILE=~/sslkeylog.log ./client

SSLKEYLOGFILE=~/sslkeylog.log: 这是一个环境变量设置,指示程序在运行期间将 SSL/TLS 密钥日志输出到指定文件 ~/sslkeylog.log。这个环境变量通常用于调试和分析 SSL/TLS 流量。通过这种方式,可以保存密钥以便后续使用工具(如 Wireshark)进行抓包分析。

./client: 这是一个可执行文件的运行命令,表示在当前目录下执行名为 client 的程序。

启动客户端后可能的报错

  • failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 7168 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details.该消息表示接收缓冲区的大小不能满足程序的需求。具体来说,当前缓冲区大小为 208 KiB,而程序想要将其增加到 7168 KiB,但是实际增加后只得到了 416 KiB。

  • 原因:错误的原因主要是因为系统的 UDP 接收缓冲区的配置不足,不能满足程序的需求。QUIC 是基于 UDP 协议的,因此对于 UDP 连接的缓冲区设置会影响 QUIC 的性能和稳定性。

  • 解决方法:为了调整 UDP 缓冲区大小,可以按照以下步骤进行操作

    #将 UDP 接收和发送缓冲区的最大值设置为 8 MiB(8388608 字节)
    sudo sysctl -w net.core.rmem_max=8388608
    sudo sysctl -w net.core.wmem_max=8388608
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值