发现电脑上装着liteide,就用golang做一个TCP通讯测试(支持先启动client端和断线重连)
1、参考https://www.cnblogs.com/yin5th/p/9274495.html
server端 main.go
package main import ( "fmt" "net" ) func main() { // simple tcp server //1.listen ip+port listener, err := net.Listen("tcp", "0.0.0.0:9090") if err != nil { fmt.Printf("listen fail, err: %v\n", err) return } //2.accept client request //3.create goroutine for each request for { conn, err := listener.Accept() if err != nil { fmt.Printf("accept fail, err: %v\n", err) continue } //create goroutine for each connect go process(conn) } } func process(conn net.Conn) { defer conn.Close() for { var buf [128]byte n, err := conn.Read(buf[:]) if err != nil { fmt.Printf("read from connect failed, err: %v\n", err) break } str := string(buf[:n]) fmt.Printf("receive from client, data: %v\n", str) } }
client端 main.go
package main import ( "bufio" "fmt" "net" "os" "strings" ) func main() { conn, err := net.Dial("tcp", "localhost:9090") defer conn.Close() if err != nil { fmt.Printf("connect failed, err : %v\n", err.Error()) return } inputReader := bufio.NewReader(os.Stdin) for { input, err := inputReader.ReadString('\n') if err != nil { fmt.Printf("read from console failed, err: %v\n", err) break } trimmedInput := strings.TrimSpace(input) if trimmedInput == "Q" { break } _, err = conn.Write([]byte(trimmedInput)) if err != nil { fmt.Printf("write failed , err : %v\n", err) break } } }
2.想要交互的话,只需在c/s两端的循环中适时用conn.Read 和conn.Write,用fmt.Printf显示出来即可
3、golang []byte和string相互转换 参考 https://www.cnblogs.com/DaBing0806/p/6680750.html
4,golang 几种字符串的连接方式 参考 https://blog.csdn.net/hatlonely/article/details/79156311 和https://studygolang.com/articles/3427
4、不想出现dos窗口的话 ,参考:https://blog.csdn.net/wangkai_123456/article/details/71158341
配置: go build -ldflags "-H windowsgui"
lite IDE配置
菜单 编译→编译配置
在“自定义”页面下的 BUILDAGRS 后添加 -ldflags "-H windowsgui"
5、不是本机测试的话,服务器端口参考https://blog.csdn.net/yoie01/article/details/21488457
如果只作为本地测试的话,可以写成loaclhost:xxxx
如果是监听外网的话,则直接写端口即可 :XXXX
注意添加防火墙入站规则。允许所有程序,指定本地特定端口,协议,远程所有端口。
6,为解决断线重连问题,参考https://blog.csdn.net/mypc2010/article/details/78276702
将server端改为
//服务端反向控制 package main import ( "bytes" "fmt" "net" ) func main() { //监听 listener, err := net.Listen("tcp", ":9097") if err != nil { fmt.Printf("listen fail, err: %v\n", err) return } //循环,接受和处理 for { conn, err := listener.Accept() if err != nil { fmt.Printf("accept fail, err: %v\n", err) continue } //在goroutine中处理 go process(conn) } } func process(conn net.Conn) { defer conn.Close() for { //先向管道中写数据 var buffer bytes.Buffer buffer.WriteString("i am server,ip: ") buffer.WriteString(LocalIp()) ipa := buffer.String() conn.Write([]byte(ipa)) //再从管道中读数据 var buf [2048]byte n, err := conn.Read(buf[:]) if err != nil { fmt.Printf("read from connect failed, err: %v\n", err) break } str := string(buf[:n]) fmt.Printf("received from client, data: %v\n", str) } } //显示本机IP func LocalIp() string { addrs, err := net.InterfaceAddrs() if err != nil { fmt.Println(err) } var ip string = "localhost" for _, address := range addrs { if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { if ipnet.IP.To4() != nil { ip = ipnet.IP.String() } } } return ip }
将client端改为
//client package main import ( "bytes" "errors" "fmt" "net" "os" "time" ) func main() { for { conn, err := net.Dial("tcp", "192.168.0.239:9097") if err != nil { fmt.Fprintf(os.Stderr, "Fatal error:%s", err.Error()) } else { defer conn.Close() doWork(conn) } time.Sleep(3 * time.Second) } } //显示本机IP func LocalIp() string { addrs, err := net.InterfaceAddrs() if err != nil { fmt.Println(err) } var ip string = "localhost" for _, address := range addrs { if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { if ipnet.IP.To4() != nil { ip = ipnet.IP.String() } } } return ip } //接收服务端发来的消息 func ClientMsgHandler(conn net.Conn, ch chan int) { var buf [2048]byte n, _ := conn.Read(buf[:]) str := string(buf[:n]) fmt.Printf("cmd from S, data: %v\n", str) if len(str) == 0 { //服务端无返回信息 ch <- 2 } //reply to server var buffer bytes.Buffer buffer.WriteString("i received,i am clent ip: ") buffer.WriteString(LocalIp()) str2 := buffer.String() data2 := []byte(str2) conn.Write(data2) } //解决断线重连问题 func doWork(conn net.Conn) error { ch := make(chan int, 100) ticker := time.NewTicker(time.Second) defer ticker.Stop() for { select { case stat := <-ch: if stat == 2 { return errors.New("None Msg") } case <-ticker.C: ch <- 1 go ClientMsgHandler(conn, ch) case <-time.After(time.Second * 10): defer conn.Close() fmt.Println("timeout") } } return nil }
可先启动多个client,再启动server,且断线重连。