当前位置 博文首页 > 在Go中构建并发TCP服务器

    在Go中构建并发TCP服务器

    作者:Mihalis Tsoukalos 时间:2021-07-02 18:36

    开发一个并发TCP服务器,该服务器仅使用大约65行GO代码生成随机数。

    TCP和UDP服务器随处可见,通过TCP/IP网络为网络客户端提供服务。在本文中,我将在GO编程语言,返回随机数。对于来自TCP客户端的每个传入连接,TCP服务器将启动一个新的goroutine来处理该请求。
    你可以找到这个项目,concTCP.go,在GitHub上。

    处理TCP连接

    程序的逻辑可以在handleConnection()职能,其实现方式如下:

    func handleConnection(c net.Conn) {
        fmt.Printf("Serving %s\n", c.RemoteAddr().String())
        for {
            netData, err := bufio.NewReader(c).ReadString('\n')
            if err != nil {
                fmt.Println(err)
                return
            }
            temp := strings.TrimSpace(string(netData))
            if temp == "STOP" {
                break
            }
            result := strconv.Itoa(random()) + "\n"
            c.Write([]byte(string(result)))
        }
        c.Close()
    }

    如果TCP客户端发送“STOP”字符串,那么为该特定TCP客户端提供服务的goroutine将终止;否则,TCP服务器将向TCP客户端发送随机数。for循环确保TCP客户端将在TCP客户端所需的时间内得到服务。控件中的GO代码。for循环从tcp客户端逐行读取数据,使用bufio.NewReader(c).ReadString('\n')并使用c.Write([]byte(string(result)))。

    兼容并蓄

    main()函数的实现告诉TCP服务器每次必须为TCP客户端服务时启动一个新的goroutine:

    func main() {
        arguments := os.Args
        if len(arguments) == 1 {
            fmt.Println("Please provide a port number!")
            return
        }
        PORT := ":" + arguments[1]
        l, err := net.Listen("tcp4", PORT)
        if err != nil {
            fmt.Println(err)
            return
        }
        defer l.Close()
        rand.Seed(time.Now().Unix())
        for {
            c, err := l.Accept()
            if err != nil {
                fmt.Println(err)
                return
            }
            go handleConnection(c)
        }
    }

    首先,main()确保程序至少有一个命令行参数。注意,现有代码不检查给定的命令行参数是否为有效的TCP端口号。但是,如果给定的值不是有效的tcp端口号,则调用net.Listen()如果出现类似以下错误消息,将失败:

    $ go run concTCP.go 12a
    listen tcp4: lookup tcp4/12a: nodename nor servname provided, or not known
    $ go run concTCP.go -10
    listen tcp4: address -10: invalid port

    net.Listen()Call用于告诉GO程序接受网络连接,从而充当服务器。的返回值net.Listen()是net.Conn类型,它实现io.Reader和io.Writer接口。main()函数还调用rand.Seed()函数来初始化随机数生成器。最后,for循环允许程序继续接受新的tcp客户端。Accept()的实例来处理handleConnection()函数,该函数作为goroutines执行。

    net.Listen()的第一个参数

    的第一个参数net.Listen()函数定义将要使用的网络类型,而第二个参数定义服务器地址以及服务器将侦听的端口号。第一个参数的有效值是TCP、tcp 4(仅IPv 4-)、tcp 6(仅IPv 6)、UDP、udp 4(仅IPv 4-)、udp 6(仅IPv 6)、IP、IP4(仅IPv 4-)、ip6(仅IPv 6)、Unix(Unix套接字)、Unixgram和UnixPacket。

    运行中的并发tcp服务器。

    ctCP.go需要一个命令行参数,这是它要侦听的端口号。在为TCP客户端提供服务时,从ctCP.go获得的输出将类似于以下内容:

    $ go run concTCP.go 8001
    Serving 127.0.0.1:62554
    Serving 127.0.0.1:62556

    输出netstat(1)可以验证ctCP.go服务于多个TCP客户端,同时侦听更多连接:

    $ netstat -anp TCP | grep 8001
    tcp4    0   0 127.0.0.1.8001     127.0.0.1.62556    ESTABLISHED
    tcp4    0   0 127.0.0.1.62556    127.0.0.1.8001     ESTABLISHED
    tcp4    0   0 127.0.0.1.8001     127.0.0.1.62554    ESTABLISHED
    tcp4    0   0 127.0.0.1.62554    127.0.0.1.8001     ESTABLISHED
    tcp4    0   0 *.8001         *.*          LISTEN

    前面命令输出的最后一行通知我们,有一个进程侦听端口8001,这意味着您仍然可以连接到TCP端口8001。前两行验证是否存在使用端口号8001和62556的已建立的tcp网络连接。类似地,第三行和第四行验证是否存在使用端口号8001和62554的另一个已建立的tcp连接。

    下图显示了在为多个TCP客户端提供服务时,ctCP.go的输出:

    ctCP.go TCP服务器正在运行。

    类似地,下面的映像显示了两个TCP客户机的输出,它们使用nc(1)效用:

    摘要

    因此,您刚刚学习了如何开发一个并发TCP服务器,该服务器使用大约65行GO代码生成随机数,这是相当令人印象深刻的!如果希望TCP服务器执行不同的任务,只需更改handleConnection()功能。

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对站长博客的支持。如果你想了解更多相关内容请查看下面相关链接

    jsjbwy
    下一篇:没有了