在Go中構建并發(fā)TCP服務器
開發(fā)一個并發(fā)TCP服務器,該服務器僅使用大約65行GO代碼生成隨機數(shù)。
TCP和UDP服務器隨處可見,通過TCP/IP網(wǎng)絡為網(wǎng)絡客戶端提供服務。在本文中,我將在GO編程語言,返回隨機數(shù)。對于來自TCP客戶端的每個傳入連接,TCP服務器將啟動一個新的goroutine來處理該請求。
你可以找到這個項目,concTCP.go,在GitHub上。
處理TCP連接
程序的邏輯可以在handleConnection()職能,其實現(xiàn)方式如下:
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客戶端發(fā)送“STOP”字符串,那么為該特定TCP客戶端提供服務的goroutine將終止;否則,TCP服務器將向TCP客戶端發(fā)送隨機數(shù)。for循環(huán)確保TCP客戶端將在TCP客戶端所需的時間內(nèi)得到服務??丶械腉O代碼。for循環(huán)從tcp客戶端逐行讀取數(shù)據(jù),使用bufio.NewReader(c).ReadString('\n')并使用c.Write([]byte(string(result)))。
兼容并蓄
main()函數(shù)的實現(xiàn)告訴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()確保程序至少有一個命令行參數(shù)。注意,現(xiàn)有代碼不檢查給定的命令行參數(shù)是否為有效的TCP端口號。但是,如果給定的值不是有效的tcp端口號,則調(diào)用net.Listen()如果出現(xiàn)類似以下錯誤消息,將失?。?/p>
$ 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程序接受網(wǎng)絡連接,從而充當服務器。的返回值net.Listen()是net.Conn類型,它實現(xiàn)io.Reader和io.Writer接口。main()函數(shù)還調(diào)用rand.Seed()函數(shù)來初始化隨機數(shù)生成器。最后,for循環(huán)允許程序繼續(xù)接受新的tcp客戶端。Accept()的實例來處理handleConnection()函數(shù),該函數(shù)作為goroutines執(zhí)行。
net.Listen()的第一個參數(shù)
的第一個參數(shù)net.Listen()函數(shù)定義將要使用的網(wǎng)絡類型,而第二個參數(shù)定義服務器地址以及服務器將偵聽的端口號。第一個參數(shù)的有效值是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。
運行中的并發(fā)tcp服務器。
ctCP.go需要一個命令行參數(shù),這是它要偵聽的端口號。在為TCP客戶端提供服務時,從ctCP.go獲得的輸出將類似于以下內(nèi)容:
$ 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網(wǎng)絡連接。類似地,第三行和第四行驗證是否存在使用端口號8001和62554的另一個已建立的tcp連接。
下圖顯示了在為多個TCP客戶端提供服務時,ctCP.go的輸出:
ctCP.go TCP服務器正在運行。
類似地,下面的映像顯示了兩個TCP客戶機的輸出,它們使用nc(1)效用:
摘要
因此,您剛剛學習了如何開發(fā)一個并發(fā)TCP服務器,該服務器使用大約65行GO代碼生成隨機數(shù),這是相當令人印象深刻的!如果希望TCP服務器執(zhí)行不同的任務,只需更改handleConnection()功能。
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關內(nèi)容請查看下面相關鏈接
相關文章
Goland 的安裝及激活教程(window、linux下安裝)
這篇文章主要介紹了Golang Goland 的安裝及激活詳細教程,包括window下安裝goland和linux下安裝goland,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10Go調(diào)度器學習之goroutine調(diào)度詳解
這篇文章主要為大家詳細介紹了Go調(diào)度器中goroutine調(diào)度的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2023-03-03