日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
在Go中實(shí)現(xiàn)一個(gè)支持并發(fā)的TCP服務(wù)端

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

站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到河間網(wǎng)站設(shè)計(jì)與河間網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、網(wǎng)站空間、企業(yè)郵箱。業(yè)務(wù)覆蓋河間地區(qū)。

TCP 和 UDP 服務(wù)端隨處可見(jiàn),它們基于 TCP/IP 協(xié)議棧,通過(guò)網(wǎng)絡(luò)為客戶端提供服務(wù)。在這篇文章中,我將介紹如何使用 ??Go 語(yǔ)言?? 開(kāi)發(fā)一個(gè)用于返回隨機(jī)數(shù)、支持并發(fā)的 TCP 服務(wù)端。對(duì)于每一個(gè)來(lái)自 TCP 客戶端的連接,它都會(huì)啟動(dòng)一個(gè)新的 goroutine(輕量級(jí)線程)來(lái)處理相應(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)保證的。具體來(lái)說(shuō),??for?? 循環(huán)中的代碼使用了 ??bufio.NewReader(c).ReadString('\n')?? 來(lái)逐行讀取客戶端發(fā)來(lái)的數(shù)據(jù),并使用 ??c.Write([]byte(string(result)))?? 來(lái)返回?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 來(lái)為這個(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)有代碼并沒(méi)有檢查這個(gè)參數(shù)是否為有效的 TCP 端口號(hào)。不過(guò),如果它是一個(gè)無(wú)效的 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ù)來(lái)接受 TCP 客戶端的連接請(qǐng)求,并以 goroutine 的方式來(lái)運(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)聽(tīng)的地址和端口號(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ù),來(lái)指定監(jiān)聽(tīng)的端口號(hào)。當(dāng)它開(kāi)始服務(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)聽(tīng)建立連接的請(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)聽(tīng) 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 代碼來(lái)開(kāi)發(fā)一個(gè)生成隨機(jī)數(shù)、支持并發(fā)的 TCP 服務(wù)端,這真是太棒了!如果你想要讓你的 TCP 服務(wù)端執(zhí)行別的任務(wù),只需要修改 ??handleConnection()?? 函數(shù)即可。


網(wǎng)站名稱:在Go中實(shí)現(xiàn)一個(gè)支持并發(fā)的TCP服務(wù)端
標(biāo)題鏈接:http://www.dlmjj.cn/article/dhodocs.html