溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

在Go中構(gòu)建并發(fā)TCP服務(wù)器

發(fā)布時(shí)間:2020-09-25 13:57:31 來(lái)源:腳本之家 閱讀:131 作者:Mihalis Tsoukalos 欄目:編程語(yǔ)言

開(kāi)發(fā)一個(gè)并發(fā)TCP服務(wù)器,該服務(wù)器僅使用大約65行GO代碼生成隨機(jī)數(shù)。

TCP和UDP服務(wù)器隨處可見(jiàn),通過(guò)TCP/IP網(wǎng)絡(luò)為網(wǎng)絡(luò)客戶(hù)端提供服務(wù)。在本文中,我將在GO編程語(yǔ)言,返回隨機(jī)數(shù)。對(duì)于來(lái)自TCP客戶(hù)端的每個(gè)傳入連接,TCP服務(wù)器將啟動(dòng)一個(gè)新的goroutine來(lái)處理該請(qǐng)求。
你可以找到這個(gè)項(xiàng)目,concTCP.go,在GitHub上。

處理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客戶(hù)端發(fā)送“STOP”字符串,那么為該特定TCP客戶(hù)端提供服務(wù)的goroutine將終止;否則,TCP服務(wù)器將向TCP客戶(hù)端發(fā)送隨機(jī)數(shù)。for循環(huán)確保TCP客戶(hù)端將在TCP客戶(hù)端所需的時(shí)間內(nèi)得到服務(wù)??丶械腉O代碼。for循環(huán)從tcp客戶(hù)端逐行讀取數(shù)據(jù),使用bufio.NewReader(c).ReadString('\n')并使用c.Write([]byte(string(result)))。

兼容并蓄

main()函數(shù)的實(shí)現(xiàn)告訴TCP服務(wù)器每次必須為T(mén)CP客戶(hù)端服務(wù)時(shí)啟動(dòng)一個(gè)新的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()確保程序至少有一個(gè)命令行參數(shù)。注意,現(xiàn)有代碼不檢查給定的命令行參數(shù)是否為有效的TCP端口號(hào)。但是,如果給定的值不是有效的tcp端口號(hào),則調(diào)用net.Listen()如果出現(xiàn)類(lèi)似以下錯(cuò)誤消息,將失?。?/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)絡(luò)連接,從而充當(dāng)服務(wù)器。的返回值net.Listen()是net.Conn類(lèi)型,它實(shí)現(xiàn)io.Reader和io.Writer接口。main()函數(shù)還調(diào)用rand.Seed()函數(shù)來(lái)初始化隨機(jī)數(shù)生成器。最后,for循環(huán)允許程序繼續(xù)接受新的tcp客戶(hù)端。Accept()的實(shí)例來(lái)處理handleConnection()函數(shù),該函數(shù)作為goroutines執(zhí)行。

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

的第一個(gè)參數(shù)net.Listen()函數(shù)定義將要使用的網(wǎng)絡(luò)類(lèi)型,而第二個(gè)參數(shù)定義服務(wù)器地址以及服務(wù)器將偵聽(tīng)的端口號(hào)。第一個(gè)參數(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。

運(yùn)行中的并發(fā)tcp服務(wù)器。

ctCP.go需要一個(gè)命令行參數(shù),這是它要偵聽(tīng)的端口號(hào)。在為T(mén)CP客戶(hù)端提供服務(wù)時(shí),從ctCP.go獲得的輸出將類(lèi)似于以下內(nèi)容:

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

輸出netstat(1)可以驗(yàn)證ctCP.go服務(wù)于多個(gè)TCP客戶(hù)端,同時(shí)偵聽(tī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)程偵聽(tīng)端口8001,這意味著您仍然可以連接到TCP端口8001。前兩行驗(yàn)證是否存在使用端口號(hào)8001和62556的已建立的tcp網(wǎng)絡(luò)連接。類(lèi)似地,第三行和第四行驗(yàn)證是否存在使用端口號(hào)8001和62554的另一個(gè)已建立的tcp連接。

下圖顯示了在為多個(gè)TCP客戶(hù)端提供服務(wù)時(shí),ctCP.go的輸出:

在Go中構(gòu)建并發(fā)TCP服務(wù)器

ctCP.go TCP服務(wù)器正在運(yùn)行。

類(lèi)似地,下面的映像顯示了兩個(gè)TCP客戶(hù)機(jī)的輸出,它們使用nc(1)效用:

在Go中構(gòu)建并發(fā)TCP服務(wù)器

摘要

因此,您剛剛學(xué)習(xí)了如何開(kāi)發(fā)一個(gè)并發(fā)TCP服務(wù)器,該服務(wù)器使用大約65行GO代碼生成隨機(jī)數(shù),這是相當(dāng)令人印象深刻的!如果希望TCP服務(wù)器執(zhí)行不同的任務(wù),只需更改handleConnection()功能。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)億速云的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI