Golang中如何限制netListener的带宽
Golang中如何限制netListener的带宽 你好! 请问如何实现 netListener 的带宽速度限制? 我尝试过一些模块,但完全不起作用……
3 回复
标准库的监听器不提供任何带宽限制或限流功能。
你可能需要自行实现这一功能。
同时,限流更多是监听器接受连接后产生的读取器/连接的工作。
func main() {
fmt.Println("hello world")
}
更多关于Golang中如何限制netListener的带宽的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我正在开发一个SOCKS代理,需要实现速度限制功能。
我尝试了那个模块,但即使对于单个连接,它也没有限制速度。
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库。

