Skip to content

Instantly share code, notes, and snippets.

@masakielastic
Created March 2, 2026 07:29
Show Gist options
  • Select an option

  • Save masakielastic/2fa45c274bb2ea87b52bbe978dd3e3d3 to your computer and use it in GitHub Desktop.

Select an option

Save masakielastic/2fa45c274bb2ea87b52bbe978dd3e3d3 to your computer and use it in GitHub Desktop.
go-quic で echo サーバー
// server.go
package main
import (
"context"
"crypto/tls"
"fmt"
"io"
"log"
"github.com/quic-go/quic-go"
)
const (
addr = "127.0.0.1:4242"
alpn = "example-quic"
certF = "cert.pem"
keyF = "key.pem"
)
func main() {
tlsConf := &tls.Config{
Certificates: []tls.Certificate{mustLoadTLS(certF, keyF)},
NextProtos: []string{alpn},
}
ln, err := quic.ListenAddr(addr, tlsConf, nil)
if err != nil {
log.Fatal(err)
}
log.Println("QUIC server listening on", addr)
for {
conn, err := ln.Accept(context.Background()) // *quic.Conn
if err != nil {
log.Println("accept conn:", err)
continue
}
go handleConn(conn)
}
}
func handleConn(conn *quic.Conn) {
log.Println("new conn from", conn.RemoteAddr())
for {
st, err := conn.AcceptStream(context.Background()) // *quic.Stream
if err != nil {
log.Println("accept stream:", err)
return
}
go handleStream(st)
}
}
func handleStream(st *quic.Stream) {
defer st.Close()
buf := make([]byte, 4096)
n, err := st.Read(buf)
if err != nil && err != io.EOF {
log.Println("read:", err)
return
}
msg := string(buf[:n])
log.Println("received:", msg)
if _, err := st.Write([]byte("echo: " + msg)); err != nil {
log.Println("write:", err)
}
}
func mustLoadTLS(certFile, keyFile string) tls.Certificate {
c, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
log.Fatal(err)
}
return c
}
// client.go
package main
import (
"context"
"crypto/tls"
"fmt"
"io"
"log"
"time"
"github.com/quic-go/quic-go"
)
const (
addr = "127.0.0.1:4242"
alpn = "example-quic"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
tlsConf := &tls.Config{
InsecureSkipVerify: true, // テスト用途
NextProtos: []string{alpn},
}
conn, err := quic.DialAddr(ctx, addr, tlsConf, nil) // *quic.Conn
if err != nil {
log.Fatal(err)
}
defer conn.CloseWithError(0, "done")
st, err := conn.OpenStreamSync(ctx) // *quic.Stream
if err != nil {
log.Fatal(err)
}
if _, err := st.Write([]byte("hello over quic")); err != nil {
log.Fatal(err)
}
buf := make([]byte, 4096)
n, err := st.Read(buf)
if err != nil && err != io.EOF {
log.Fatal(err)
}
fmt.Println(string(buf[:n]))
}

go-quic で echo サーバー

go mod init example-quic
go get github.com/quic-go/quic-go
go run server.go
go run client.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment