问题:
A、B、C三台计算机,A和B可以通讯,B和C可以通讯,但是A和C不能通讯(红色的虚线)。那如何让A和C通讯?
解决方案:
需要在B计算机,安装一个端口映射程序,其功能:A发送数据给B,B再把数据透传到C,C处理完后,把数据回应给B,B电脑透传给A。
代码实现:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106package 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) }
代码说明:
复制代码
1
2
3
4
5
6local_server, err := net.Listen("tcp", localAddress) if nil != err { fmt.Printf("开启socket [%s]失败rn", localAddress) return }
B电脑的TCP服务监听。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14for { 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。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19func 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。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18func 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协议下内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复