偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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


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


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

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

處理 TCP 連接

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

支持并發(fā)

在 ??main()?? 函數(shù)的實(shí)現(xiàn)部分,每當(dāng) TCP 服務(wù)端收到 TCP 客戶端的連接請(qǐng)求,它都會(huì)啟動(dòng)一個(gè)新的 goroutine 來為這個(gè)請(qǐng)求提供服務(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()?? 確保程序至少有一個(gè)命令行參數(shù)。注意,現(xiàn)有代碼并沒有檢查這個(gè)參數(shù)是否為有效的 TCP 端口號(hào)。不過,如果它是一個(gè)無效的 TCP 端口號(hào),??net.Listen()?? 就會(huì)調(diào)用失敗,并返回一個(gè)錯(cuò)誤信息,類似下面這樣:

$ 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??,后者實(shí)現(xiàn)了 ??io.Reader?? 和 ??io.Writer?? 接口。此外,??main()?? 函數(shù)中還調(diào)用了 ??rand.Seed()?? 函數(shù),用于初始化隨機(jī)數(shù)生成器。最后,??for?? 循環(huán)允許程序一直使用 ??Accept()?? 函數(shù)來接受 TCP 客戶端的連接請(qǐng)求,并以 goroutine 的方式來運(yùn)行 ??handleConnection(c)?? 函數(shù),處理客戶端的后續(xù)請(qǐng)求。

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

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

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

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

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

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

$ 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

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

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

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

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

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

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

總結(jié)

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

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

2024-01-02 13:58:04

GoREST API語(yǔ)言

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:25:35

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

2020-06-15 08:13:42

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

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圖編程語(yǔ)言

2011-03-15 15:43:39

Windows AzuWCF

2011-03-15 16:12:00

Windows AzuWCF

2021-07-02 07:18:19

Goresults通道類型

2024-01-08 08:36:29

HTTPGo代理服務(wù)器

2025-05-20 09:39:57

GogRPC微服務(wù)
點(diǎn)贊
收藏

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