golang的socket編程

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

在Go的net包中定義了很多類型、函數和方法用來網路編程,其中IP的定義如下:

type IP []byte
輸入的IP地址需要解析,以免輸入的是錯誤格式的IP地址:
func ParseIP(s string) IP
參數s可以是字串類型的ipv4或ipv6地址,如果解析錯誤會返回nil。

在Go語言的net包中有一個類型TCPConn,這個類型可以用來作為用戶端和伺服器端互動的通道,他有兩個主要的函數:

func (c *TCPConn) Write(b []byte) (n int, err os.Error)func (c *TCPConn) Read(b []byte) (n int, err os.Error)
TCPConn可以用在用戶端和伺服器端來讀寫資料。而TCP的地址資訊用TCPAddr來表示:
type TCPAddr struct {    IP IP    Port int}
通過ResolveTCPAddr擷取一個TCPAddr:
func ResolveTCPAddr(net, addr string) (*TCPAddr, os.Error)
  • net參數是"tcp4"、"tcp6"、"tcp"中的任意一個,分別表示TCP(IPv4-only),TCP(IPv6-only)或者TCP(IPv4,IPv6的任意一個).
  • addr表示網域名稱或者IP地址,例如"www.google.com:80" 或者"127.0.0.1:22".
通過net包中的DialTCP函數來建立一個TCP串連,並返回一個TCPConn類型的對象,當串連建立時伺服器端也建立一個同類型的對象,此時用戶端和伺服器段通過各自擁有的TCPConn對象來進行資料交換。一般而言,用戶端通過TCPConn對象將請求資訊發送到伺服器端,讀取伺服器端響應的資訊。伺服器端讀取並解析來自用戶端的請求,並返回應答資訊,這個串連只有當任一端關閉了串連之後才失效,不然這串連可以一直在使用。建立串連的函數定義如下:
func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error)
  • net參數是"tcp4"、"tcp6"、"tcp"中的任意一個,分別表示TCP(IPv4-only)、TCP(IPv6-only)或者TCP(IPv4,IPv6的任意一個)
  • laddr表示本機地址,一般設定為nil
  • raddr表示遠端服務地址
用戶端代碼如下所示:
package mainimport (    "fmt"    "io/ioutil"    "net"    "os")func main() {    if len(os.Args) != 2 {        fmt.Fprintf(os.Stderr, "Usage: %s host:port ", os.Args[0])        os.Exit(1)    }    service := os.Args[1]    tcpAddr, err := net.ResolveTCPAddr("tcp4", service)    checkError(err)    conn, err := net.DialTCP("tcp", nil, tcpAddr)    checkError(err)    _, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))    checkError(err)    result, err := ioutil.ReadAll(conn)    checkError(err)    fmt.Println(string(result))    os.Exit(0)}func checkError(err error) {    if err != nil {        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())        os.Exit(1)    }}
在伺服器端我們需要綁定服務到指定的非啟用連接埠,並監聽此連接埠,當有用戶端請求到達的時候可以接收到來自用戶端串連的請求。net包中有相應功能的函數,函數定義如下:
func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error)func (l *TCPListener) Accept() (c Conn, err os.Error)
伺服器端代碼如下:
package mainimport (    "fmt"    "net"    "os"    "time"    "strconv")func main() {    service := ":1200"    tcpAddr, err := net.ResolveTCPAddr("tcp4", service)    checkError(err)    listener, err := net.ListenTCP("tcp", tcpAddr)    checkError(err)    for {        conn, err := listener.Accept()        if err != nil {            continue        }        go handleClient(conn)    }}func handleClient(conn net.Conn) {    conn.SetReadDeadline(time.Now().Add(2 * time.Minute)) // set 2 minutes timeout    request := make([]byte, 128) // set maxium request length to 128KB to prevent flood attack    defer conn.Close()  // close connection before exit    for {        read_len, err := conn.Read(request)        if err != nil {            fmt.Println(err)            break        }        if read_len == 0 {            break // connection already closed by client        } else if string(request) == "timestamp" {            daytime := strconv.FormatInt(time.Now().Unix(), 10)            conn.Write([]byte(daytime))        } else {            daytime := time.Now().String()            conn.Write([]byte(daytime))         }        request = make([]byte, 128) // clear last read content    }}func checkError(err error) {    if err != nil {        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())        os.Exit(1)    }}

TCP有很多串連控制函數,我們平常用到比較多的有如下幾個函數:

func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)

設定建立串連的逾時時間,用戶端和伺服器端都適用,當超過設定時間時,串連自動關閉。

func (c *TCPConn) SetReadDeadline(t time.Time) errorfunc (c *TCPConn) SetWriteDeadline(t time.Time) error

用來設定寫入/讀取一個串連的逾時時間。當超過設定時間時,串連自動關閉。

func (c *TCPConn) SetKeepAlive(keepalive bool) os.Error

設定用戶端是否和伺服器端保持長串連,可以降低建立TCP串連時的握手開銷,對於一些需要頻繁交換資料的應用情境比較適用。

Go語言套件中處理UDP Socket和TCP Socket不同的地方就是在伺服器端處理多個用戶端請求資料包的方式不同,UDP缺少了對用戶端串連請求的Accept函數。其他基本幾乎一模一樣,只是TCP換成了UDP而已。UDP的幾個主要函數如下所示:

func ResolveUDPAddr(net, addr string) (*UDPAddr, os.Error)func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err os.Error)func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err os.Error)func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Errorfunc (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err os.Error)
UDP的用戶端代碼如下:
package mainimport (    "fmt"    "net"    "os")func main() {    if len(os.Args) != 2 {        fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0])        os.Exit(1)    }    service := os.Args[1]    udpAddr, err := net.ResolveUDPAddr("udp4", service)    checkError(err)    conn, err := net.DialUDP("udp", nil, udpAddr)    checkError(err)    _, err = conn.Write([]byte("anything"))    checkError(err)    var buf [512]byte    n, err := conn.Read(buf[0:])    checkError(err)    fmt.Println(string(buf[0:n]))    os.Exit(0)}func checkError(err error) {    if err != nil {        fmt.Fprintf(os.Stderr, "Fatal error ", err.Error())        os.Exit(1)    }}
伺服器端的代碼如下:
package mainimport (    "fmt"    "net"    "os"    "time")func main() {    service := ":1200"    udpAddr, err := net.ResolveUDPAddr("udp4", service)    checkError(err)    conn, err := net.ListenUDP("udp", udpAddr)    checkError(err)    for {        handleClient(conn)    }}func handleClient(conn *net.UDPConn) {    var buf [512]byte    _, addr, err := conn.ReadFromUDP(buf[0:])    if err != nil {        return    }    daytime := time.Now().String()    conn.WriteToUDP([]byte(daytime), addr)}func checkError(err error) {    if err != nil {        fmt.Fprintf(os.Stderr, "Fatal error ", err.Error())        os.Exit(1)    }}
可見TCP與UDP的conn對象是不同的,前者是net.Conn,後者是net.UDPConn。另外UDP的伺服器端的讀寫是要帶著地址的,這個地址是用戶端的地址。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.