Golang中如何限制netListener的带宽

Golang中如何限制netListener的带宽 你好! 请问如何实现 netListener 的带宽速度限制? 我尝试过一些模块,但完全不起作用……

3 回复

标准库的监听器不提供任何带宽限制或限流功能。

你可能需要自行实现这一功能。

同时,限流更多是监听器接受连接后产生的读取器/连接的工作。

func main() {
    fmt.Println("hello world")
}

更多关于Golang中如何限制netListener的带宽的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我正在开发一个SOCKS代理,需要实现速度限制功能。

我尝试了那个模块,但即使对于单个连接,它也没有限制速度。

pkg.go.dev

bandwidth package - github.com/gerritjvv/tcpshaper/bandwidth - Go Packages

Package bandwidth provides rate limiting utilities and middleware for TCP connections.

在Golang中限制netListener的带宽可以通过包装net.Conn实现流量控制。以下是一个使用令牌桶算法实现带宽限制的示例:

package main

import (
    "io"
    "net"
    "time"
    "golang.org/x/time/rate"
)

type rateLimitedConn struct {
    net.Conn
    reader io.Reader
    writer io.Writer
}

func NewRateLimitedConn(conn net.Conn, limit rate.Limit) net.Conn {
    limiter := rate.NewLimiter(limit, int(limit))
    
    return &rateLimitedConn{
        Conn:   conn,
        reader: newRateLimitedReader(conn, limiter),
        writer: newRateLimitedWriter(conn, limiter),
    }
}

type rateLimitedReader struct {
    r       io.Reader
    limiter *rate.Limiter
}

func newRateLimitedReader(r io.Reader, limiter *rate.Limiter) io.Reader {
    return &rateLimitedReader{
        r:       r,
        limiter: limiter,
    }
}

func (r *rateLimitedReader) Read(p []byte) (n int, err error) {
    n, err = r.r.Read(p)
    if n > 0 {
        r.limiter.WaitN(r.limiter.ReserveN(time.Now(), n))
    }
    return
}

type rateLimitedWriter struct {
    w       io.Writer
    limiter *rate.Limiter
}

func newRateLimitedWriter(w io.Writer, limiter *rate.Limiter) io.Writer {
    return &rateLimitedWriter{
        w:       w,
        limiter: limiter,
    }
}

func (w *rateLimitedWriter) Write(p []byte) (n int, err error) {
    n, err = w.w.Write(p)
    if n > 0 {
        w.limiter.WaitN(w.limiter.ReserveN(time.Now(), n))
    }
    return
}

func (c *rateLimitedConn) Read(p []byte) (n int, err error) {
    return c.reader.Read(p)
}

func (c *rateLimitedConn) Write(p []byte) (n int, err error) {
    return c.writer.Write(p)
}

// 使用示例
func main() {
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        panic(err)
    }
    
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        
        // 限制为 1MB/s (8Mbps)
        limitedConn := NewRateLimitedConn(conn, rate.Limit(1024*1024))
        
        go handleConnection(limitedConn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()
    // 处理连接逻辑
}

另一个更简单的实现方案:

package main

import (
    "io"
    "net"
    "time"
)

type bandwidthConn struct {
    net.Conn
    bandwidth int // bytes per second
}

func NewBandwidthConn(conn net.Conn, bandwidth int) net.Conn {
    return &bandwidthConn{
        Conn:      conn,
        bandwidth: bandwidth,
    }
}

func (bc *bandwidthConn) Read(p []byte) (n int, err error) {
    start := time.Now()
    n, err = bc.Conn.Read(p)
    
    if n > 0 && bc.bandwidth > 0 {
        expected := time.Duration(n) * time.Second / time.Duration(bc.bandwidth)
        elapsed := time.Since(start)
        
        if expected > elapsed {
            time.Sleep(expected - elapsed)
        }
    }
    
    return n, err
}

func (bc *bandwidthConn) Write(p []byte) (n int, err error) {
    start := time.Now()
    n, err = bc.Conn.Write(p)
    
    if n > 0 && bc.bandwidth > 0 {
        expected := time.Duration(n) * time.Second / time.Duration(bc.bandwidth)
        elapsed := time.Since(start)
        
        if expected > elapsed {
            time.Sleep(expected - elapsed)
        }
    }
    
    return n, err
}

// 在accept循环中使用
func acceptConnections(listener net.Listener) {
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        
        // 限制为100KB/s
        limitedConn := NewBandwidthConn(conn, 100*1024)
        go handleClient(limitedConn)
    }
}

如果需要更精确的控制,可以使用第三方库如github.com/juju/ratelimit

import (
    "github.com/juju/ratelimit"
    "io"
    "net"
)

type rateLimitedConn struct {
    net.Conn
    bucket *ratelimit.Bucket
}

func NewRateLimitedConn(conn net.Conn, rate int64) net.Conn {
    bucket := ratelimit.NewBucketWithRate(float64(rate), rate)
    
    return &rateLimitedConn{
        Conn:   conn,
        bucket: bucket,
    }
}

func (rlc *rateLimitedConn) Read(p []byte) (n int, err error) {
    n, err = rlc.Conn.Read(p)
    if n > 0 {
        rlc.bucket.Wait(int64(n))
    }
    return
}

func (rlc *rateLimitedConn) Write(p []byte) (n int, err error) {
    n, err = rlc.Conn.Write(p)
    if n > 0 {
        rlc.bucket.Wait(int64(n))
    }
    return
}

这些实现通过在读写操作后添加延迟来限制带宽,第一个方案使用标准库的rate包,第二个方案使用简单的时间计算,第三个方案使用第三方ratelimit库。

回到顶部