Golang中实现一对多net.Conn连接的方法

Golang中实现一对多net.Conn连接的方法 我有一个本地的 net.Conn 连接和若干个远程连接。我需要从远程连接读取数据,将数据写入本地连接,从本地连接获取响应,然后将响应发送回最初发送消息的那个远程连接。这该如何实现?

2 回复

你如何从这些远程连接读取数据?能否展示一些相关代码?

更多关于Golang中实现一对多net.Conn连接的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中实现一对多的连接转发,可以使用连接映射和通道来管理。以下是一个实现示例:

package main

import (
    "io"
    "log"
    "net"
    "sync"
)

type ConnectionManager struct {
    localConn   net.Conn
    remoteConns map[string]net.Conn
    mu          sync.RWMutex
}

func NewConnectionManager(local net.Conn) *ConnectionManager {
    return &ConnectionManager{
        localConn:   local,
        remoteConns: make(map[string]net.Conn),
    }
}

func (cm *ConnectionManager) AddRemote(conn net.Conn) {
    cm.mu.Lock()
    defer cm.mu.Unlock()
    cm.remoteConns[conn.RemoteAddr().String()] = conn
}

func (cm *ConnectionManager) RemoveRemote(addr string) {
    cm.mu.Lock()
    defer cm.mu.Unlock()
    delete(cm.remoteConns, addr)
}

func (cm *ConnectionManager) ForwardToLocal(remote net.Conn) {
    defer remote.Close()
    
    // 为每个远程连接创建唯一标识
    remoteAddr := remote.RemoteAddr().String()
    
    // 从远程读取数据并写入本地
    buf := make([]byte, 4096)
    for {
        n, err := remote.Read(buf)
        if err != nil {
            if err != io.EOF {
                log.Printf("从远程读取错误: %v", err)
            }
            cm.RemoveRemote(remoteAddr)
            return
        }
        
        // 写入本地连接
        _, err = cm.localConn.Write(buf[:n])
        if err != nil {
            log.Printf("写入本地错误: %v", err)
            return
        }
        
        // 从本地读取响应
        respBuf := make([]byte, 4096)
        respLen, err := cm.localConn.Read(respBuf)
        if err != nil {
            log.Printf("从本地读取错误: %v", err)
            return
        }
        
        // 将响应写回对应的远程连接
        _, err = remote.Write(respBuf[:respLen])
        if err != nil {
            log.Printf("写回远程错误: %v", err)
            return
        }
    }
}

func main() {
    // 建立本地连接
    localConn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        log.Fatal(err)
    }
    defer localConn.Close()
    
    cm := NewConnectionManager(localConn)
    
    // 监听远程连接
    listener, err := net.Listen("tcp", ":9090")
    if err != nil {
        log.Fatal(err)
    }
    defer listener.Close()
    
    for {
        remoteConn, err := listener.Accept()
        if err != nil {
            log.Printf("接受连接错误: %v", err)
            continue
        }
        
        cm.AddRemote(remoteConn)
        go cm.ForwardToLocal(remoteConn)
    }
}

如果需要更精确的请求-响应匹配,可以使用带标识的协议:

type Request struct {
    ID      string
    Data    []byte
    Conn    net.Conn
}

func (cm *ConnectionManager) ForwardWithID(remote net.Conn) {
    remoteAddr := remote.RemoteAddr().String()
    requestChan := make(chan Request, 100)
    responseChan := make(chan Request, 100)
    
    // 读取远程请求
    go func() {
        buf := make([]byte, 4096)
        for {
            n, err := remote.Read(buf)
            if err != nil {
                close(requestChan)
                return
            }
            requestChan <- Request{
                ID:   remoteAddr,
                Data: append([]byte{}, buf[:n]...),
                Conn: remote,
            }
        }
    }()
    
    // 处理请求和响应
    for req := range requestChan {
        // 写入本地
        cm.localConn.Write(req.Data)
        
        // 读取本地响应
        respBuf := make([]byte, 4096)
        respLen, _ := cm.localConn.Read(respBuf)
        
        // 发送回对应远程连接
        if req.Conn != nil {
            req.Conn.Write(respBuf[:respLen])
        }
    }
}

这个实现确保了每个远程连接的请求都能获得对应的响应,通过连接映射管理多个远程连接与单个本地连接的通信。

回到顶部