概述
问题:
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协议下的端口映射透传功能所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复