发现电脑上装着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网关
你是否也存在过这样的需求,想要公开一个接口到网络上.但是还得加点权限,否则被人乱调用就不好了.这个权限验证的过程,最好越简单越好,可能只是对比两个字符串相等就够了.一般情况下我们遇到这种需要,就是在函 ...
随机推荐
- 1. 七种join的sql编写
一.join图 二.sql演示 a.创建演示表及数据 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ----------------------- ...
- C#设计模式之十外观模式(Facade Pattern)【结构型】
一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...
- learnVUE-note
title: learnVUE-note date: 2018-02-27 15:57:37 tags: categories: 前端技术 --- 本文是自己在学习Vue中的 VUE事件处理 在事件处 ...
- mapper接口方法参数
mapper接口中的方法只有一个参数,是不影响程序员开发的可以将参数指定为 pojo类型 或 map
- jfinal框架学习过程
刚刚学习jfinal,通过一天左右的时间大体上理解了这个框架的用法,我对他的理解是JFinal 是基于 Java 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速.代码量少.学习简单.功 ...
- writing objects : 值%停住
在git bush 中使用命令:git config --global http.postBuffer 524288000 因为git上传,限定一次push命令的buffer大小.
- 关于数据分析的4点心得:维度、指标、KPI
1.看数据看维度 在对某一项业务或者业务的某个模块进行分析时,可以从大小两个角度去切入分析. 首先站在广阔的视角去看待一些数据.比如对某个产品(消费品),就要分析在大环境下是一个什么样的数据,如市场排 ...
- Navicat Premium for Mac 破解版地址
找了好几个都不能使用 试了一下这个 可以使用 放地址:http://www.orsoon.com/Mac/85386.html
- 浅谈Android 混淆和加固
混淆: 针对项目代码,代码混淆通常将代码中的各种元素(变量.函数.类名等)改为无意义的名字,使得阅读的人无法通过名称猜测其用途,增大反编译者的理解难度. 虽然代码混淆可以提高反编译的门槛,但是对开发者 ...
- Kotlin入门(29)任务Runnable
任务Runnable定义了一个可以独立运行的代码片段,通常用于界面控件的延迟处理,比如有时为了避免同时占用某种资源造成冲突,有时则是为了反复间隔刷新界面从而产生动画效果.运行一个任务也有多种形式,既可 ...