热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

1、参考https:www.cnblogs.comyin5thp9274495.htmlserver端main.gopackagemainimport(

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,且断线重连。

 


推荐阅读
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
author-avatar
Ww不孤单_584
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有