tcp并发服务器_在Go中构建并发TCP服务器

tcp并发服务器

本文是Mihalis Tsoukalos的“围棋”系列的一部分。 阅读第1部分: 在Go中创建随机,安全的密码

TCP和UDP服务器无处不在,通过TCP / IP网络为网络客户端提供服务。 在本文中,我将解释如何使用Go编程语言开发并发TCP服务器,该服务器返回随机数。 对于来自TCP客户端的每个传入连接,TCP服务器将启动一个新的goroutine来处理该请求。

您可以在GitHub上找到该项目concTCP.go

处理TCP连接

程序的逻辑可以在handleConnection()函数的Go代码中找到,该代码的实现如下:


   
   
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 ()
}
for循环可确保在TCP客户端需要的时间范围内为TCP客户端提供服务。 for循环中的Go代码使用bufio.NewReader(c).ReadString('\n')从TCP客户端读取数据,并使用c.Write([]byte(string(result))) 。 (您可能会发现网络标准Go软件包文档很有帮助。)

并发

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()调用用于告诉Go程序接受网络连接,从而充当服务器。 net.Listen()的返回值是net.Conn类型,该类型实现io.Readerio.Writer接口。 main()函数还调用rand.Seed()函数以初始化随机数生成器。 最后, for循环允许程序继续使用Accept()接受新的TCP客户端,这些客户端将由handleConnection()函数的实例处理,该实例作为goroutine执行。

net.Listen()的第一个参数

net.Listen()函数的第一个参数定义将使用的网络类型,而第二个参数定义服务器地址以及服务器将侦听的端口号。 第一个参数的有效值为tcp,tcp4(仅IPv4),tcp6(仅IPv6),udp,udp4(仅IPv4),udp6(仅IPv6),ip,ip4(仅IPv4),ip6(仅限IPv6),Unix(Unix套接字),Unixgram和Unixpacket。

运行中的并发TCP服务器

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


   
   
$ go run concTCP . go 8001
Serving 127 . 0 . 0 . 1 : 62554
Serving 127 . 0 . 0 . 1 : 62556

netstat(1)的输出可以验证concTCP.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。前两行验证存在已建立的TCP网络连接使用端口号8001和62556。类似地,第三和第四行验证是否存在另一个使用端口号8001和62554的已建立TCP连接。

此图显示了服务多个TCP客户端时concTCP.go的输出:

The concTCP.go TCP server in action.

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

类似地,下图显示了使用nc(1)实用程序实现的两个TCP客户端的输出:

Using the nc(1) utility as the TCP client to concTCP.go.

使用nc(1)实用程序作为concTCP.go的TCP客户端。

您可以在Wikipedia上找到有关nc(1) (也称为netcat(1)更多信息。

摘要

因此,您刚刚学习了如何开发并发TCP服务器,该服务器使用大约65行Go代码生成随机数,这真是令人印象深刻! 如果希望TCP服务器执行其他工作,只需更改handleConnection()函数的实现即可。

翻译自: https://opensource.com/article/18/5/building-concurrent-tcp-server-go

tcp并发服务器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值