发现电脑上装着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 []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端和断线重连)的更多相关文章
- 在电脑上装ubuntu12.04系统,内核文件是那个?
在电脑上装ubuntu12.04系统,我们能看到的是根文件系统,那么内核文件(zlmage)是那个? ???
- 【Golang 接口自动化00】为什么要用Golang做自动化?
为什么使用Golang做自动化 顺应公司的趋势学习了Golang之后,因为没有开发那么多的时间和项目来实践,怕步此前学习Java缺少练习遗忘殆尽的后尘,决定利用工作之余的时间把此前用Python的写的 ...
- 使用golang写一个redis-cli
使用golang写一个redis-cli 0. redis通信协议 redis的客户端(redis-cli)和服务端(redis-server)的通信是建立在tcp连接之上, 两者之间数据传输的编码解 ...
- 用struts2标签如何从数据库获取数据并在查询页面显示。最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量。
最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变 ...
- Golang做的验证码(2)
前面一篇文章介绍了2个用Golang做的验证码 http://www.cnblogs.com/ghj1976/p/3392847.html 这里再补充几个: 1.在GAE上使用的Google的验证码 ...
- golang(5):编写WebSocket服务,client和html5调用
本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/46882777 转载请必须注明出处! 1.关于websocket HTML5定义了 ...
- golang实现一个代理服务器(proxy)学习笔记
golang是google公司开发一门新的编程语言.对于老的程序员来说,学习一门语言最好的方式,不过是做一个小的项目. 网上看到这一篇使用golang开发proxy的例子,觉得挺有意思.希望通过实际模 ...
- 今天做一个项目的时候,要在一个编辑的jsp页面的textarea标签设置value属性,结果发现他没有value属性,但是是编辑页面又必须要回显要修改的内容,所以在参考了w3cschool之后很轻松的解决了这个问题。
今天做一个项目的时候,要在一个编辑的jsp页面的textarea标签设置value属性,结果发现他没有value属性,但是是编辑页面又必须要回显要修改的内容,所以在参考了w3cschool之后很轻松的 ...
- 如何使用Golang实现一个API网关
你是否也存在过这样的需求,想要公开一个接口到网络上.但是还得加点权限,否则被人乱调用就不好了.这个权限验证的过程,最好越简单越好,可能只是对比两个字符串相等就够了.一般情况下我们遇到这种需要,就是在函 ...
随机推荐
- Netty实战十之编解码器框架
编码和解码,或者数据从一种特定协议的格式到另一种格式的转换.这些任务将由通常称为编解码器的组件来处理.Netty提供了多种组件,简化了为了支持广泛的协议而创建自定义的编解码器的过程.例如,如果你正在构 ...
- MyBatis学习笔记(二) Executor
一.概述 当我们打开一个SqlSession的时候,我们就完成了操作数据库的第一步,那MyBatis是如何执行Sql的呢?其实MyBatis的增删改查都是通过Executor执行的,Executor和 ...
- python中的tcp
目录 TCP简介 TCP介绍 TCP特点 TCP与UDP的不同点 udp通信模型 TCP通信模型 tcp客户端 tcp服务器 tcp注意点 TCP简介 TCP介绍 TCP协议,传输控制协议(英语:Tr ...
- 设计模式之原型模式——Java语言描述
原型模式是用于创建重复对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的方式 这种模式实现了一个原型接口,该接口用于创建当前对象的克隆.当直接创建对象的代价比较大时,则适 ...
- Spider-two
一.网络数据加密:1. md5 / sha1 不可逆加密算法: 结果是十六进制数, 结果不可逆, 多用于文件验证 import hashlib md5_obj = hashlib.md5() sha1 ...
- 中文汉字和常见英文数字等的unicode编码范围
- 一个JVM进程启动后里面有几个线程
在写Java程序时,通常我们管只有一个main函数(而没有别的Thread或Runnable的程序)叫单线程程序.但是我们写的这个所谓的单线程程序只是JVM这个程序中的一个线程,JVM本身是一个多线程 ...
- 方向键控制圆球运动(简易)(js)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Jmeter学习——http请求Content encoding的重要性
今天在测试一个接口的时候,遇到的问题,困扰了我一天 下面是一个接口,使用的是post请求,Content-Type为application/json 返回参数如下: 瞬间懵逼了!!!为什么呢?渠道是存 ...
- servlet请求和响应的过程
1.加载 Servlet类被加载到Java虚拟机中,并且实例化.在这个过程中,web容器(例如tomcat)会调用Servlet类的公开无参构造函数,产生一个Servlet类的实例对象.默认情况下Se ...