在Go中实现一个支持并发的TCP服务器,开发一个生成随机数并支持并发的TCP服务器,只需要大约65行代码。TCP和UDP服务器随处可见。它们基于TCP/IP协议栈,通过网络向客户端提供服务。在本文中,我将介绍如何使用Go语言开发一个返回随机数并支持并发的TCP服务器。对于来自TCP客户端的每个连接,它都会启动一个新的goroutine(轻量级线程)来处理相应的请求。你可以在GitHub上找到这个项目的源代码:concTcp.go。该程序处理TCP连接的主要逻辑在handleConnection()函数中,实现如下:funchandleConnection(cnet.Conn){fmt.Printf("Serving%s\n",c.RemoteAddr().String())for{netData,err:=bufio.NewReader(c).ReadString('\n')iferr!=nil{fmt.Println(err)return}temp:=strings.TrimSpace(string(netData))iftemp=="STOP"{break}result:=strconv.Itoa(random())+"\n"c.Write([]byte(string(result)))}c.Close()}如果TCP如果客户端发送“STOP”字符串,为其服务的goroutine将终止;否则,TCP服务器将返回一个随机数给它。只要客户端不主动终止,服务端就会继续提供服务,这是for循环保证的。具体来说,for循环中的代码使用bufio.NewReader(c).ReadString('\n')逐行读取客户端发送的数据,使用c.Write([]byte(string(result)))返回数据(生成的随机数)。您可以在Go的net标准包文档中了解更多信息。支持并发在main()函数的实现部分,每当TCP服务器收到TCP客户端的连接请求时,就会启动一个新的goroutine来为请求服务。funcmain(){arguments:=os.Argsiflen(arguments)==1{fmt.Println("Pleaseprovideaportnumber!")return}PORT:=":"+arguments[1]l,err:=net.Listen("tcp4",PORT)iferr!=nil{fmt.Println(err)return}deferl.Close()rand.Seed(time.Now().Unix())for{c,错误:=l.Accept()iferr!=nil{fmt.Println(err)return}gohandleConnection(c)}}首先,main()确保程序至少有一个命令行参数。请注意,现有代码不会检查此参数是否为有效的TCP端口号。但是,如果是无效的TCP端口号,net.Listen()将失败并返回错误消息,类似于以下内容:$gorunconcTCP.go12alistentcp4:lookuptcp4/12a:nodenamenorservnameprovided,ornotknown$gorunconcTCP.go-10listentcp4:address-10:invalidportnet.Listen()函数用来告诉Go接受网络连接,从而承担服务器的角色。它的返回类型是net.Conn,它实现了io.Reader和io.Writer接口。此外,main()函数还调用了rand.Seed()函数来初始化随机数生成器。最后,for循环让程序始终使用Accept()函数来接受来自TCP客户端的连接请求,并将handleConnection(c)函数作为一个goroutine来运行以处理来自客户端的后续请求。net.Listen()的第一个参数net.Listen()函数的第一个参数定义了使用的网络类型,而第二个参数定义了服务器监听的地址和端口号。第一个参数的有效值为tcp、tcp4、tcp6、udp、udp4、udp6、ip、ip4、ip6、Unix(Unix套接字)、Unixgram和Unixpacket,其中:tcp4、udp4和ip4仅接受IPv4地址,而tcp6、udp6和ip6仅接受IPv6地址。服务器并发测试concTCP.go需要一个命令行参数指定监听的端口号。当它开始为TCP客户端提供服务时,您将得到类似如下的输出:$gorunconcTCP.go8001Serving127.0.0.1:62554Serving127.0.0.1:62556netstat的输出可以通过congTCP.goServingmultiple来确认TCP客户端并继续监听连接建立请求:$netstat-anpTCP|grep8001tcp400127.0.0.1.8001127.0.0.1.62556ESTABLISHEDtcp400127.0.0.1.62556127.0.0.1.8001ESTABLISHEDtcp400127.0.0.1.8001127.0.0.1.62554ESTABLISHEDtcp400127.0.0.1.62554127.0.0.1.8001ESTABLISHEDtcp400*.8001*.*listen上面的输出中显示了一行LISTENonport8001,表示可以继续连接TCP的8001端口。第一行和第二行显示在8001和62556端口已经建立了TCP网络连接。同理,第三行和第四行表明还有一个已建立的TCP网络连接使用端口8001和62554连接。下图显示了服务多个TCP客户端时concTCP.go的输出:concTCP.goTCP服务器测试同样,下图显示了两个TCP客户端(使用nc工具)的输出:使用nc工具作为concTCP.go的TCP客户端您可以在维基百科上找到有关nc(即netcat)的更多信息。总结现在你已经学会了如何在大约65行Go代码中开发一个生成随机数并支持并发的TCP服务器,这太棒了!如果您希望您的TCP服务器执行其他任务,只需修改handleConnection()函数即可。
