问题:
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 in\r\n")
// #关闭socket
defer r.Close()
defer w.Close()
fmt.Printf("Info: Mapping > (%s) -> (%s) > N bytes.\r\n", 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].\r\n", 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]失败\r\n", 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: %s\n", err.Error())
continue
}
go tcp_mapping_request(localConn, remote_ip, remote_port)
fmt.Printf("Event: Receive mapping request from [%s]\r\n", 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]失败\r\n", localAddress)
return
}
B电脑的TCP服务监听。
for {
localConn, err := local_server.Accept()
if nil != err {
fmt.Printf("Unable to accept a request, error: %s\n", err.Error())
continue
}
go tcp_mapping_request(localConn, remote_ip, remote_port)
fmt.Printf("Event: Receive mapping request from [%s]\r\n", 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].\r\n", 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 in\r\n")
// #关闭socket
defer r.Close()
defer w.Close()
fmt.Printf("Info: Mapping > (%s) -> (%s) > N bytes.\r\n", 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操作。
|