发现电脑上装着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网关
你是否也存在过这样的需求,想要公开一个接口到网络上.但是还得加点权限,否则被人乱调用就不好了.这个权限验证的过程,最好越简单越好,可能只是对比两个字符串相等就够了.一般情况下我们遇到这种需要,就是在函 ...
随机推荐
- 16.QT-QMap和QHash解析
QMap QMap原型为class QMap <K,T>,其中K表示键,T表示值,K和T属于映射关系. QMap会根据K来自动进行升序键排序 QMap中的K类型必须重载operator & ...
- SpringBoot 配置 Servlet、Filter、Listener
SpringBoot 配置 Servlet.Filter.Listener 在SpringBoot应用中,嵌入式的 Servlet 3.0+ 容器不会直接使用 ServletContainerInit ...
- [算法总结] 13 道题搞定 BAT 面试——字符串
1. KMP 算法 谈到字符串问题,不得不提的就是 KMP 算法,它是用来解决字符串查找的问题,可以在一个字符串(S)中查找一个子串(W)出现的位置.KMP 算法把字符匹配的时间复杂度缩小到 O(m+ ...
- Java8 使用stream实现各种list操作
利用java8新特性,可以用简洁高效的代码来实现一些数据处理. 定义1个Apple对象: public class Apple { private Integer id; private String ...
- 汇编语言--微机CPU的指令系统(五)(字符串操作指令)
(11)字符串操作指令 字符串操作指令的实质是对一片连续存储单元进行处理,这片存储单元是由隐含指针DS:SI或ES:DI来指定的.字符串操作指令可对内存单元按字节.字或双字进行处理,并能根据操作对象的 ...
- 工作笔记-table问题汇总(vue单文件组件)
1.vue: computed里定义的数据,在其他地方不能再重新赋值,会报错: Computed property "xxxxxx" was assigned to but it ...
- Html5、css、JavaScript基础
一.HTML学习 HTML样式Css 内联样式- 在HTML元素中使用"style" 属性 内部样式表 -在HTML文档头部 <head> 区域使用<style& ...
- 洛谷P2866 [USACO06NOV]糟糕的一天Bad Hair Day(单调栈)
题目描述 Some of Farmer John's N cows (1 ≤ N ≤ 80,000) are having a bad hair day! Since each cow is self ...
- 微信小程序心得
首先从官方文档给的框架说起,微信小程序官方文档给出了app.js, app.json, app.wxss. 先从这三个文件说起. - app.js 这个文件是整个小程序的入口文件,开发者的逻辑代码在这 ...
- Javascript 对象 - 数组对象
JavaScript核心对象 数组对象Array 字符串对象String 日期对象Date 数学对象Math 数组对象 数组对象是用来在单一的变量名中存储一系列的值.数组是在编程语言中经常使用的一种数 ...