golang实现简单的TCP代理

TCP Proxy

go 复制代码
package main

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

// go实现简单的TCP代理

// TCPProxy 是一个 TCP 代理
type TCPProxy struct {
	listenAddr string
	targetAddr string
}

// NewTCPProxy 创建一个新的 TCP 代理
func NewTCPProxy(listenAddr, targetAddr string) *TCPProxy {
	return &TCPProxy{
		listenAddr: listenAddr,
		targetAddr: targetAddr,
	}
}

// Serve 开始监听并代理 TCP 连接
func (p *TCPProxy) Serve() error {
	// 监听 TCP 连接
	listener, err := net.Listen("tcp", p.listenAddr)
	if err != nil {
		return err
	}
	defer listener.Close()
	log.Printf("tcp proxy listening at: %s\n", listener.Addr())
	// 处理 TCP 连接
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Printf("listener accept error: %s\n", err)
			continue
		}
		go p.handleConnection(conn)
	}
}

// handleConnection 处理 TCP 连接
func (p *TCPProxy) handleConnection(conn net.Conn) {
	defer conn.Close() // 关闭代理连接
	log.Printf("accepted new connection %s\n", conn.RemoteAddr())
	// 创建目标连接
	targetConn, err := net.Dial("tcp", p.targetAddr)
	if err != nil {
		log.Printf("dial target addr: %s error: %s\n", p.targetAddr, err)
		return
	}
	defer targetConn.Close() // 关闭目标连接
	log.Printf("tcp proxy client addr: %s\n", targetConn.LocalAddr())
	// 处理 TCP 流 ,在客户端和目标服务器之间双向转发数据
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() {
		defer wg.Done()
		n, err := io.Copy(conn, targetConn)
		if err != nil {
			log.Printf("copy bytes from %s to %s error: %s", conn.RemoteAddr(), targetConn.RemoteAddr(), err)
			return
		}
		log.Printf("copied %d bytes from %s to %s", n, conn.RemoteAddr(), targetConn.RemoteAddr())

	}()
	go func() {
		defer wg.Done()
		n, err := io.Copy(targetConn, conn)
		if err != nil {
			log.Printf("copy bytes from %s to %s error: %s", targetConn.RemoteAddr(), conn.RemoteAddr(), err)
			return
		}
		log.Printf("copied %d bytes from %s to %s", n, targetConn.RemoteAddr(), conn.RemoteAddr())
	}()
	// 等待两个复制操作完成
	wg.Wait()
}

func main() {
	proxy := NewTCPProxy("127.0.0.1:8080", "127.0.0.1:8081")
	if err := proxy.Serve(); err != nil {
		log.Fatal(err)
	}
}

Server

go 复制代码
package main

import (
	"bufio"
	"log"
	"net"
)

// TCP Server端测试
// handle 处理函数
func handle(conn net.Conn) {
	defer conn.Close() // 关闭连接
	reader := bufio.NewReader(conn)
	for {
		var buf [512]byte
		n, err := reader.Read(buf[:]) // 读取数据
		if err != nil {
			log.Printf("read from client err: %s\n", err)
			break
		}
		log.Printf("read %d bytes from client\n", n)
		recvStr := string(buf[:n])
		log.Printf("received data from client: %s\n", recvStr)
		n, err = conn.Write([]byte(recvStr)) // 发送数据
		if err != nil {
			log.Printf("write data to client err: %s\n", err)
			return
		}
		log.Printf("write %d bytes to client\n", n)
	}
}

func main() {
	listener, err := net.Listen("tcp", "127.0.0.1:8081")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("server listening at: %s\n", listener.Addr())
	for {
		conn, err := listener.Accept() // 监听客户端的连接请求
		if err != nil {
			log.Printf("listener accept error: %s\n", err)
			continue
		}
		go handle(conn) // 启动一个goroutine来处理客户端的连接请求
	}
}

Client

go 复制代码
package main

import (
	"bufio"
	"log"
	"net"
	"os"
	"strings"
)

// TCP 客户端
func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("client addr: %s\n", conn.LocalAddr())
	defer conn.Close() // 关闭TCP连接
	inputReader := bufio.NewReader(os.Stdin)
	for {
		input, _ := inputReader.ReadString('\n') // 读取用户输入
		inputInfo := strings.Trim(input, "\r\n")
		if strings.ToUpper(inputInfo) == "Q" { // 如果输入q就退出
			return
		}
		n, err := conn.Write([]byte(inputInfo)) // 发送数据
		if err != nil {
			log.Printf("write data to server err: %s\n", err)
			return
		}
		log.Printf("write %d bytes to server\n", n)
		buf := [512]byte{}
		n, err = conn.Read(buf[:])
		if err != nil {
			log.Printf("read data from server err: %s\n", err)
			return
		}
		log.Printf("read %d bytes from server\n", n)
		log.Printf("received data from server: %s\n", string(buf[:n]))
	}
}
相关推荐
科研邪修法1 小时前
培训PDF保护配置:把需求转换成可验收权限
linux·服务器·网络
程序员Query5 小时前
day01-认识Go语言 + golang环境的安装
开发语言·后端·golang
略懂而已1 天前
安装SSL后网站速度变慢?
网络·网络协议·ssl
云上工程笔记1 天前
RDMA / IB 高速互联 GPU 云对比:多机训练网络性能与价格
网络·gpu算力·gpu
codigger1 天前
负载均衡到底在干嘛?7 个场景给你说明白
网络·架构·负载均衡
喵了几个咪1 天前
GoWind Flow 拆解:一个 Go 工作流引擎与它的双模式设计器
开发语言·人工智能·后端·golang
codeejun1 天前
每日一Go·MySQL-14、慢 SQL 产生原因全解
sql·mysql·golang
吴建旭 智宅焕2 天前
智能家居全国交付中执行端能力跃迁的架构设计:从标准装调到交付专家的系统化路径
网络·网络协议·智能家居
Eyfcom2 天前
〖全球化架构 05〗跨国网络专线优化:QUIC 协议与 SD-WAN 在跨境传输中的实战
网络·架构·跨境物流快递系统·全球化架构