热门标签 | 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,且断线重连。

 


推荐阅读
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
author-avatar
lingdong369
一个脱离低级趣味的高级动物。
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有