我是靠谱客的博主 紧张大白,最近开发中收集的这篇文章主要介绍go实现TCP协议下的端口映射透传功能,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

问题:

A、B、C三台计算机,A和B可以通讯,B和C可以通讯,但是A和C不能通讯(红色的虚线)。那如何让A和C通讯?

 

解决方案:

需要在B计算机,安装一个端口映射程序,其功能:A发送数据给B,B再把数据透传到C,C处理完后,把数据回应给B,B电脑透传给A。

代码实现:

package main

import (
	"fmt"
	"net"
	"os"
	"io"
)

func tcp_mapping_worker(r net.Conn, w net.Conn) {

	fmt.Printf("tcp_mapping_worker inrn")

	// #关闭socket
	defer r.Close()
	defer w.Close()

	fmt.Printf("Info: Mapping > (%s) -> (%s) > N bytes.rn", r.RemoteAddr(), w.RemoteAddr())

	_, err := io.Copy(w, r)

	if nil != err{
		fmt.Println("Info: Copy: ", err)
	}

	return
}

func tcp_mapping_request(local_conn net.Conn, remote_ip string, remotePort string) {

	// 目标IP和端口
	remoteAddress := fmt.Sprintf("%s:%s", remote_ip, remotePort)

	//
	remote_conn, err := net.Dial("tcp", remoteAddress)

	if nil != err {
		local_conn.Close()
		fmt.Printf("Error: Unable to connect to the remote server[%s:%s].rn", remote_ip, remotePort)
		return
	}

	//
	go tcp_mapping_worker(local_conn, remote_conn)
	go tcp_mapping_worker(remote_conn, local_conn)

}


func ServerSocket(remote_ip string, remote_port string, local_ip string, local_port string) {

	// 监听端口
	localAddress := fmt.Sprintf("%s:%s", local_ip, local_port)

	local_server, err := net.Listen("tcp", localAddress)

	if nil != err {
		fmt.Printf("开启socket [%s]失败rn", localAddress)
		return
	}

	defer local_server.Close()

	local_message := fmt.Sprintf("Event: Starting mapping service on %s:%s ...", local_ip, local_port)

	fmt.Println(local_message)

	for {
		
		localConn, err := local_server.Accept()

		if nil != err {
			//local_server.Close()
			fmt.Printf("Unable to accept a request, error: %sn", err.Error())
            continue
		}

		
		go tcp_mapping_request(localConn, remote_ip, remote_port)

		fmt.Printf("Event: Receive mapping request from [%s]rn", localConn.RemoteAddr())

	}

}


func main() {


	remoteIP := “132.xxx.xxx.xxx”
	remotePort := “9090”


	localIP := “192.168.1.100”
	localPort := “8080”


	fmt.Println("remote_IP:", remoteIP)
	fmt.Println("remote_port:", remotePort)
	fmt.Println("local_IP:", localIP)
	fmt.Println("local_port:", localPort)

	ServerSocket(remoteIP, remotePort, localIP, localPort)

}


代码说明:

	local_server, err := net.Listen("tcp", localAddress)

	if nil != err {
		fmt.Printf("开启socket [%s]失败rn", localAddress)
		return
	}

B电脑的TCP服务监听。

	for {
		
		localConn, err := local_server.Accept()

		if nil != err {
			fmt.Printf("Unable to accept a request, error: %sn", err.Error())
            continue
		}

		go tcp_mapping_request(localConn, remote_ip, remote_port)

		fmt.Printf("Event: Receive mapping request from [%s]rn", localConn.RemoteAddr())

	}

Accept等待A的客户端连接,一直阻塞,所以一直死循环等待连接。连接成功,启动一个协程tcp_mapping_request。

func tcp_mapping_request(local_conn net.Conn, remote_ip string, remotePort string) {

	// 目标IP和端口
	remoteAddress := fmt.Sprintf("%s:%s", remote_ip, remotePort)

	//
	remote_conn, err := net.Dial("tcp", remoteAddress)

	if nil != err {
		local_conn.Close()
		fmt.Printf("Error: Unable to connect to the remote server[%s:%s].rn", remote_ip, remotePort)
		return
	}

	//
	go tcp_mapping_worker(local_conn, remote_conn)
	go tcp_mapping_worker(remote_conn, local_conn)

}

协程tcp_mapping_request,Dial连接C服务前置,若连接成功,分别建立协程B->C和C->B的tcp_mapping_worker。

func tcp_mapping_worker(r net.Conn, w net.Conn) {

	fmt.Printf("tcp_mapping_worker inrn")

	// #关闭socket
	defer r.Close()
	defer w.Close()

	fmt.Printf("Info: Mapping > (%s) -> (%s) > N bytes.rn", r.RemoteAddr(), w.RemoteAddr())

	_, err := io.Copy(w, r)

	if nil != err{
		fmt.Println("Info: Copy: ", err)
	}

	return
}

协程tcp_mapping_worker,使用接口io.Copy,把r通道复制到w通道,这个是点睛之处,省掉TCP接口读read和write接口,直接使用copy接口,就完成了read和write操作。

最后

以上就是紧张大白为你收集整理的go实现TCP协议下的端口映射透传功能的全部内容,希望文章能够帮你解决go实现TCP协议下的端口映射透传功能所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部