1. 程式人生 > >go語言快速入門 IPC之Socket 9

go語言快速入門 IPC之Socket 9

技術分享 img roo listening ref 上進 typename 特性 ngs

多進程之間的通信常見的手段有管道/信號量/共享內存/Socket等,在上篇文章中介紹了管道的使用方法。管道在多進程通信中使用方便但是也具局限性,當通信雙方在不同的機器上的時候通信方式更多采用Socket方式。在這篇文章中我們將會繼續探索如何使用go所提供的net包等實現TCP和UDP方式的Socket通信。

傳輸層協議

OSI模型

OSI七層模型,簡單來說,下三層主要負責數據通信,而上三層主要負責數據處理。處於第四層的傳輸層是通信子網和資源子網的接口和橋梁,整體起到承上啟下的作用。而TCP和UDP則是傳輸層的協議。
技術分享圖片

TCP和UDP的區別

TCP和UDP最大的區別在於是否是面向連接的協議,作為面向連接的TCP協議,以此決定了在本質上是否是安全可靠的特性。
技術分享圖片

TCP通信

無論TCP方式還是UDP方式,常見的場景應用會分為服務器端和客戶端的類型。作為面向連接的TCP方式,服務器端的應用一般會綁定到某一端口,然後再此端口上進行監聽,當其受到客戶端的連接時便會進行交互。

Server端實現

[root@liumiaocn goprj]# cat basic-tcp-server.go
package main

import "fmt"
import "os"
import "net"
import "time"

func main() {
        //get a tcp address
        tcp_address, err := net.ResolveTCPAddr("tcp4"
, ":8848") if err != nil { fmt.Println("Error happened when getting a tcp address...", err) os.Exit(1) } //listen to the tcp address tcp_listener, err := net.ListenTCP("tcp", tcp_address) if err != nil { fmt.Println("Error happened when listening to the tcp address..."
, err) os.Exit(1) } //greeting words str_header := "Hello, this is information from tcp server , and current time is : " //main loop of tcp server for { //waiting connection from client tcp_connection, err := tcp_listener.Accept() if err != nil { continue } //get the current time infor str_time := time.Now().String() //set greeting words for client connection str_greetings := str_header + str_time //send information to client tcp_connection.Write([]byte(str_greetings)) tcp_connection.Close() } } [root@liumiaocn goprj]#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

客戶端實現

[root@liumiaocn goprj]# cat basic-tcp-client.go
package main

import "fmt"
import "io/ioutil"
import "os"
import "net"

func main() {

        //usage of client application
        if len(os.Args) != 2 {
                fmt.Fprintf(os.Stderr, "Usage: %s host:port ", os.Args[0])
                os.Exit(1)
        }

        //get a tcp address
        arg_address := os.Args[1]
        tcp_address, err := net.ResolveTCPAddr("tcp4", arg_address)
        if err != nil {
                fmt.Println("Error happened when getting a tcp address...", err)
                os.Exit(1)
        }

        //connect to a tcp server
        tcp_connection, err := net.DialTCP("tcp", nil, tcp_address)
        if err != nil {
                fmt.Println("Error happened when connecting a tcp server...", err)
                os.Exit(1)
        }

        //read information from tcp server
        str_greeting, err := ioutil.ReadAll(tcp_connection)
        if err != nil {
                fmt.Println("Error happened when reading from the tcp server...", err)
                os.Exit(1)
        }

        //display the information
        fmt.Println(string(str_greeting))
        os.Exit(0)
}
[root@liumiaocn goprj]#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

執行確認

首先將server端運行起來,等待client端的連接

[root@liumiaocn goprj]# go run basic-tcp-server.go
  • 1

運行client端,可以得到從server端發過的信息

[root@liumiaocn goprj]# go run basic-tcp-client.go 192.168.32.123:8848
Hello, this is information from tcp server , and current time is : 2017-01-31 10:56:48.590783817 -0500 EST
[root@liumiaocn goprj]#
[root@liumiaocn goprj]# go run basic-tcp-client.go 192.168.32.123:8848
Hello, this is information from tcp server , and current time is : 2017-01-31 10:56:54.969361975 -0500 EST
[root@liumiaocn goprj]#
[root@liumiaocn goprj]# go run basic-tcp-client.go 192.168.32.123:8848
Hello, this is information from tcp server , and current time is : 2017-01-31 10:57:08.226263371 -0500 EST
[root@liumiaocn goprj]#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

UDP方式

通過上述例子,可以了解到TCP方式的簡單實現。接下來看一下UDP方式。UDP作為無連接的傳輸層協議的實現,在go所提供的API可以看到,形式已經非常類似。

Server端實現

[root@liumiaocn goprj]# cat basic-udp_server.go
package main

import "fmt"
import "os"
import "net"
import "time"

func main() {
        //get a udp address
        udp_address, err := net.ResolveUDPAddr("udp4", ":9848")
        if err != nil {
                fmt.Println("Error happened when getting a udp address...", err)
                os.Exit(1)
        }

        //listen to the udp address
        udp_connection, err := net.ListenUDP("udp", udp_address)
        if err != nil {
                fmt.Println("Error happened when listening to the udp address...", err)
                os.Exit(1)
        }

        //greeting words
        str_header := "Hello, this is information from udp server , and current time is : "
        //main loop of udp server
        for {

                //read information from client
                var udp_buffer [1024]byte
                _, address, err := udp_connection.ReadFromUDP(udp_buffer[0:])
                if err != nil {
                        continue
                }

                //get the current time infor
                str_time := time.Now().String()
                //set greeting words for client connection
                str_greetings := str_header + str_time

                //send information to client
                udp_connection.WriteToUDP([]byte(str_greetings), address)
        }
}
[root@liumiaocn goprj]#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

客戶端實現

[root@liumiaocn goprj]# cat basic-udp_client.go
package main

import "fmt"
import "os"
import "net"

func main() {

        //usage of client application
        if len(os.Args) != 2 {
                fmt.Fprintf(os.Stderr, "Usage: %s host:port ", os.Args[0])
                os.Exit(1)
        }

        //get a udp address
        arg_address := os.Args[1]
        udp_address, err := net.ResolveUDPAddr("udp4", arg_address)
        if err != nil {
                fmt.Println("Error happened when getting a udp address...", err)
                os.Exit(1)
        }

        //connect to a udp server
        udp_connection, err := net.DialUDP("udp", nil, udp_address)
        if err != nil {
                fmt.Println("Error happened when connecting a udp server...", err)
                os.Exit(1)
        }

        //send information to udp server
        _, err = udp_connection.Write([]byte("hello"))
        if err != nil {
                fmt.Println("Error happened when sending message to the udp server...", err)
                os.Exit(1)
        }

        //udp buffer
        var udp_buffer [1024]byte

        //read information from udp server
        num, err := udp_connection.Read(udp_buffer[0:])
        if err != nil {
                fmt.Println("Error happened when reading from the tcp server...", err)
                os.Exit(1)
        }

        //display the information
        fmt.Println(string(udp_buffer[0:num]))
        os.Exit(0)
}
[root@liumiaocn goprj]#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

執行確認

首先將server端運行起來,等待client端的連接

[root@liumiaocn goprj]# go run basic-udp_server.go
  • 1

運行client端,可以得到從server端發過的信息

[root@liumiaocn goprj]# go run basic-udp_client.go 192.168.32.123:9848
Hello, this is information from udp server , and current time is : 2017-01-31 11:25:03.274881649 -0500 EST
[root@liumiaocn goprj]#
[root@liumiaocn goprj]# go run basic-udp_client.go 192.168.32.123:9848
Hello, this is information from udp server , and current time is : 2017-01-31 11:25:05.895074805 -0500 EST
[root@liumiaocn goprj]#
[root@liumiaocn goprj]# go run basic-udp_client.go 192.168.32.123:9848
Hello, this is information from udp server , and current time is : 2017-01-31 11:25:09.886004761 -0500 EST
[root@liumiaocn goprj]#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

總結

在這篇文章中,我們繼續討論了go語言中Socket通信的兩個簡單實例,通過這兩個例子,實現了TCP和UDP的服務器和客戶端的交互。雖然在實際中的應用還有很遠一段距離,比如並發的控制上述簡單的例子沒有涉及到,但是通過這兩個例子,已經能看出多進程通信的go的實現方式。

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!https://blog.csdn.net/jiangjunshow

go語言快速入門 IPC之Socket 9