学习项目,win会被识别为病毒,关闭病毒和威胁防护,参考 https://blog.csdn.net/u_say2what/article/details/134669122
main.go
package main
import (
"context"
"fmt"
_ "golang.org/x/sys/unix"
"golang.org/x/sys/windows"
"io"
"net"
"os"
"runtime"
"strconv"
"syscall"
"time"
)
var timeout = 1
var lc = net.ListenConfig{
Control: func(network, address string, c syscall.RawConn) error {
var opErr error
if runtime.GOOS == "windows" {
if err := c.Control(func(fd uintptr) {
opErr = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
}); err != nil {
return err
}
} else {
if err := c.Control(func(fd uintptr) {
//opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
}); err != nil {
return err
}
}
return opErr
},
}
func isIPAddress(ipStr string) bool {
ip := net.ParseIP(ipStr)
return ip != nil
}
func isPort(portStr string) bool {
port, err := strconv.Atoi(portStr)
if err != nil {
return false
}
return port > 0 && port <= 65535
}
// 示例 .\main.exe 192.168.20.0 8080 192.168.252.128 8080
func main() {
lhost := os.Args[1]
lprot := os.Args[2]
rhost := os.Args[3]
rport := os.Args[4]
if !(isIPAddress(lhost) && isPort(lprot) && isIPAddress(rhost) && isPort(rport)) {
fmt.Println("'" + os.Args[0] + "' " + "参数不能被识别")
os.Exit(0)
}
if lhost == "0.0.0.0" || lhost == "127.0.0.1" || lhost == rhost {
fmt.Println("本地地址和远程地址不能为 127.0.0.1,0.0.0.0")
os.Exit(0)
} else if lprot == rport && lhost == rhost {
fmt.Println("参数错误")
os.Exit(0)
}
laddr := fmt.Sprintf("%s:%s", lhost, lprot)
l, err := lc.Listen(context.Background(), "tcp", laddr)
go func() {
time.Sleep(2 * time.Minute)
l.Close()
if timeout == 1 {
os.Exit(0)
}
}()
if err != nil {
fmt.Println("无法监听端口:", err)
return
}
fmt.Printf("开始监听端口 %s,将转发到 %s:%s\n", lprot, rhost, rport)
for {
clientConn, err := l.Accept()
if err != nil {
continue
}
go handleClient(clientConn, rhost, lprot)
}
}
func handleClient(clientConn net.Conn, remoteHost, remotePort string) {
// 连接到目标主机
serverConn, err := net.Dial("tcp", remoteHost+":"+remotePort)
if err != nil {
fmt.Println("连接到目标主机时出错:", err)
clientConn.Close()
return
}
defer serverConn.Close()
// 在 goroutine 中进行双向数据传输
done := make(chan struct{})
go copyData(clientConn, serverConn, done)
go copyData(serverConn, clientConn, done)
// 等待任意一个goroutine完成后关闭另一个连接
<-done
clientConn.Close()
<-done
}
func copyData(dst io.Writer, src io.Reader, done chan<- struct{}) {
buf := make([]byte, 4096) // 使用较大的缓冲区,提高性能
_, err := io.CopyBuffer(dst, src, buf)
if err != nil && err != io.EOF {
fmt.Println("数据传输时出错:", err)
}
done <- struct{}{}
}
使用实例
.\main.exe 192.168.20.0 8080 192.168.252.128 8080
程序 本地地址 本地程序端口 目标地址 目标程序端口
标签:return,err,--,win,tcp,windows,fd,func,net
From: https://www.cnblogs.com/qcy-blog/p/18235262