自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

在 Go 中實現(xiàn)一個支持并發(fā)的 TCP 服務(wù)端

開發(fā) 后端
在這篇文章中,我將介紹如何使用 Go 語言 開發(fā)一個用于返回隨機數(shù)、支持并發(fā)的 TCP 服務(wù)端。對于每一個來自 TCP 客戶端的連接,它都會啟動一個新的 goroutine(輕量級線程)來處理相應(yīng)的請求。


僅用大約 65 行代碼,開發(fā)一個用于生成隨機數(shù)、支持并發(fā)的 TCP 服務(wù)端。


TCP 和 UDP 服務(wù)端隨處可見,它們基于 TCP/IP 協(xié)議棧,通過網(wǎng)絡(luò)為客戶端提供服務(wù)。在這篇文章中,我將介紹如何使用 ??Go 語言?? 開發(fā)一個用于返回隨機數(shù)、支持并發(fā)的 TCP 服務(wù)端。對于每一個來自 TCP 客戶端的連接,它都會啟動一個新的 goroutine(輕量級線程)來處理相應(yīng)的請求。

你可以在 GitHub 上找到本項目的源碼:??concTcp.go??。

處理 TCP 連接

這個程序的主要邏輯在 ??handleConnection()?? 函數(shù)中,具體實現(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” 字符串,為它提供服務(wù)的 goroutine 就會終止;否則,TCP 服務(wù)端就會返回一個隨機數(shù)給它。只要客戶端不主動終止,服務(wù)端就會一直提供服務(wù),這是由 ??for?? 循環(huán)保證的。具體來說,??for?? 循環(huán)中的代碼使用了 ??bufio.NewReader(c).ReadString('\n')?? 來逐行讀取客戶端發(fā)來的數(shù)據(jù),并使用 ??c.Write([]byte(string(result)))?? 來返回數(shù)據(jù)(生成的隨機數(shù))。你可以在 Go 的 net 標(biāo)準(zhǔn)包 ??文檔?? 中了解更多。

支持并發(fā)

在 ??main()?? 函數(shù)的實現(xiàn)部分,每當(dāng) TCP 服務(wù)端收到 TCP 客戶端的連接請求,它都會啟動一個新的 goroutine 來為這個請求提供服務(wù)。

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 端口號,??net.Listen()?? 就會調(diào)用失敗,并返回一個錯誤信息,類似下面這樣:

$ 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()?? 函數(shù)用于告訴 Go 接受網(wǎng)絡(luò)連接,因而承擔(dān)了服務(wù)端的角色。它的返回值類型是 ??net.Conn??,后者實現(xiàn)了 ??io.Reader?? 和 ??io.Writer?? 接口。此外,??main()?? 函數(shù)中還調(diào)用了 ??rand.Seed()?? 函數(shù),用于初始化隨機數(shù)生成器。最后,??for?? 循環(huán)允許程序一直使用 ??Accept()?? 函數(shù)來接受 TCP 客戶端的連接請求,并以 goroutine 的方式來運行 ??handleConnection(c)?? 函數(shù),處理客戶端的后續(xù)請求。

net.Listen() 的第一個參數(shù)

??net.Listen()?? 函數(shù)的第一個參數(shù)定義了使用的網(wǎng)絡(luò)類型,而第二個參數(shù)定義了服務(wù)端監(jiān)聽的地址和端口號。第一個參數(shù)的有效值為 ??tcp??、??tcp4??、??tcp6??、??udp??、??udp4??、??udp6??、??ip??、??ip4??、??ip6??、??Unix??(Unix 套接字)、??Unixgram?? 和 ??Unixpacket??,其中:??tcp4??、??udp4?? 和 ??ip4?? 只接受 IPv4 地址,而 ??tcp6??、??udp6?? 和 ??ip6?? 只接受 IPv6 地址。

服務(wù)端并發(fā)測試

??concTCP.go?? 需要一個命令行參數(shù),來指定監(jiān)聽的端口號。當(dāng)它開始服務(wù) TCP 客戶端時,你會得到類似下面的輸出:

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

??netstat?? 的輸出可以確認(rèn) ??congTCP.go?? 正在為多個 TCP 客戶端提供服務(wù),并且仍在繼續(xù)監(jiān)聽建立連接的請求:

$ 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

在上面輸出中,最后一行顯示了有一個進(jìn)程正在監(jiān)聽 8001 端口,這意味著你可以繼續(xù)連接 TCP 的 8001 端口。第一行和第二行顯示了有一個已建立的 TCP 網(wǎng)絡(luò)連接,它占用了 8001 和 62556 端口。相似地,第三行和第四行顯示了有另一個已建立的 TCP 連接,它占用了 8001 和 62554 端口。

下面這張圖片顯示了 ??concTCP.go?? 在服務(wù)多個 TCP 客戶端時的輸出:

concTCP.go TCP 服務(wù)端測試

類似地,下面這張圖片顯示了兩個 TCP 客戶端的輸出(使用了 ??nc?? 工具):

是用 nc 工具作為 concTCP.go 的 TCP 客戶端

你可以在 ??維基百科?? 上找到更多關(guān)于 ??nc??(即 ??netcat??)的信息。

總結(jié)

現(xiàn)在,你學(xué)會了如何用大約 65 行 Go 代碼來開發(fā)一個生成隨機數(shù)、支持并發(fā)的 TCP 服務(wù)端,這真是太棒了!如果你想要讓你的 TCP 服務(wù)端執(zhí)行別的任務(wù),只需要修改 ??handleConnection()?? 函數(shù)即可。

責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2024-01-02 13:58:04

GoREST API語言

2024-03-15 15:20:10

并發(fā)服務(wù)IP

2024-01-02 12:17:44

Go傳統(tǒng)遠(yuǎn)程

2017-04-11 16:16:48

HTTPS互聯(lián)網(wǎng)服務(wù)端

2024-04-01 13:18:15

App架構(gòu)服務(wù)端

2023-09-11 10:53:32

2022-06-14 15:07:04

IPC客戶端服務(wù)端

2021-11-10 15:18:16

JavaGo命令

2022-09-05 14:36:26

服務(wù)端TCP連接

2011-03-15 16:07:33

Windows AzuWCF

2020-06-15 08:13:42

Linux服務(wù)端并發(fā)數(shù)

2020-06-15 08:25:35

Linux 系統(tǒng) 數(shù)據(jù)

2021-04-30 09:32:38

服務(wù)端渲染SSR

2015-10-12 08:33:06

TCP網(wǎng)絡(luò)協(xié)議服務(wù)端

2020-06-28 08:10:00

GoGOSSAFUNC圖編程語言

2011-03-15 16:12:00

Windows AzuWCF

2011-03-15 15:43:39

Windows AzuWCF

2021-07-02 07:18:19

Goresults通道類型

2017-10-31 10:32:44

2023-02-26 01:37:57

goORM代碼
點贊
收藏

51CTO技術(shù)棧公眾號