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 []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 []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( * 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 []byte
n, _ := conn.Read(buf[:])
str := string(buf[:n])
fmt.Printf("cmd from S, data: %v\n", str)
if len(str) == {
//服务端无返回信息
ch <-
}
//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, ) ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case stat := <-ch:
if stat == {
return errors.New("None Msg")
}
case <-ticker.C:
ch <-
go ClientMsgHandler(conn, ch) case <-time.After(time.Second * ):
defer conn.Close()
fmt.Println("timeout")
} } return nil
}

可先启动多个client,再启动server,且断线重连。

发现电脑上装着liteide,就用golang做一个TCP通讯测试(支持先启动client端和断线重连)的更多相关文章

  1. 在电脑上装ubuntu12.04系统,内核文件是那个?

    在电脑上装ubuntu12.04系统,我们能看到的是根文件系统,那么内核文件(zlmage)是那个? ???

  2. 【Golang 接口自动化00】为什么要用Golang做自动化?

    为什么使用Golang做自动化 顺应公司的趋势学习了Golang之后,因为没有开发那么多的时间和项目来实践,怕步此前学习Java缺少练习遗忘殆尽的后尘,决定利用工作之余的时间把此前用Python的写的 ...

  3. 使用golang写一个redis-cli

    使用golang写一个redis-cli 0. redis通信协议 redis的客户端(redis-cli)和服务端(redis-server)的通信是建立在tcp连接之上, 两者之间数据传输的编码解 ...

  4. 用struts2标签如何从数据库获取数据并在查询页面显示。最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量。

    最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变 ...

  5. Golang做的验证码(2)

    前面一篇文章介绍了2个用Golang做的验证码 http://www.cnblogs.com/ghj1976/p/3392847.html  这里再补充几个: 1.在GAE上使用的Google的验证码 ...

  6. golang(5):编写WebSocket服务,client和html5调用

    本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/46882777 转载请必须注明出处! 1.关于websocket HTML5定义了 ...

  7. golang实现一个代理服务器(proxy)学习笔记

    golang是google公司开发一门新的编程语言.对于老的程序员来说,学习一门语言最好的方式,不过是做一个小的项目. 网上看到这一篇使用golang开发proxy的例子,觉得挺有意思.希望通过实际模 ...

  8. 今天做一个项目的时候,要在一个编辑的jsp页面的textarea标签设置value属性,结果发现他没有value属性,但是是编辑页面又必须要回显要修改的内容,所以在参考了w3cschool之后很轻松的解决了这个问题。

    今天做一个项目的时候,要在一个编辑的jsp页面的textarea标签设置value属性,结果发现他没有value属性,但是是编辑页面又必须要回显要修改的内容,所以在参考了w3cschool之后很轻松的 ...

  9. 如何使用Golang实现一个API网关

    你是否也存在过这样的需求,想要公开一个接口到网络上.但是还得加点权限,否则被人乱调用就不好了.这个权限验证的过程,最好越简单越好,可能只是对比两个字符串相等就够了.一般情况下我们遇到这种需要,就是在函 ...

随机推荐

  1. JSTL_Format标记库

    JSTL_Format 一:JSTL Format标记库 如有转载,请标明出处 介绍标记属性的时候,按照顺序必须写的->带有默认值的->其他的,中间用回车隔开 在jsp问价开头加上 < ...

  2. 1. volatale 关键字 -内存可见性

    package com.gf.demo01; /** * 一.volatile 关键字:但多个线程进行操作共享数据时,可以保证内存中数据可见性. * */ public class TestVolat ...

  3. mysql zip安装

    管理员运行cmd,进入bin目录1.在my.ini(mysql解压目录下)文件中复制下面内容 [client] port = 3306 [mysql] default-character-set=ut ...

  4. 8.异常_EJ

    第57条: 只针对异常情况才使用异常 异常是为了在异常情况下使用而设计的,不要将它们用于普通的控制流,也不要编写迫使它们这么做的API. 第58条: 对可恢复的情况使用受检异常,对编程错误使用运行时异 ...

  5. 【代码笔记】Web-JavaScript-JavaScript调试

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  6. cordov vue项目中调用手机原生api

    cordova不仅可以把vue项目打包成app,还可以让vue借助cordova调用手机原生的api 比如拍照 比如图片上传 比如定位 比如扫描二维码 比如支付等等 Vue Cordova教程-Vue ...

  7. Native SBS for Android

    Native SBS for Android是一款非常棒的软件,支持安卓在2D界面下左右分屏显示,并可以设置缩放比例及左右间距,横屏自动切换为左右分屏显示模式,竖屏则为正常显示.启动左右分屏模式后,将 ...

  8. python之restful api(flask)获取数据

    需要用到谷歌浏览器的扩展程序 Advanced Rest Client进行模拟请求 1.直接上代码 from flask import Flask from flask import request ...

  9. mysql中导入导出sql文件

    1.导出整个数据库: mysqldump -u用户名 -p密码 数据库名 > 导出的文件名 例:mysqldump -uroot -proot user > user.sql 2.导出一个 ...

  10. Windows Server 2016-管理站点复制(二)

    为了保持所有域控制器上的目录数据一致和最新,Active Directory 会定期复制目录更改.复制根据标准网络协议进行,并使用更改跟踪信息防止发生不必要的复制,以及使用链接值复制以提高效率. 本章 ...