這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
1. Socket 簡介
常用的 Socket 類型有兩種:流式 Socket(SOCK_STREAM)和資料報式Socket(SOCK_DGRAM)。
流式是一種連線導向的 Socket,針對於連線導向的 TCP 服務應用;
資料報式 Socket 是一種不需連線的 Socket,對應於不需連線的 UDP 服務應用
2. 網路中的進程之間如何通過 Socket 通訊呢?
網路層的“ip 地址”可以唯一標識網路中的主機,而傳輸層的“協議+連接埠”可以唯一標識主機中的應用程式(進程)。這樣利用
三元組(ip 地址,協議,連接埠)就可以標識網路的進程了,網路中需要互相通訊的進程,就可以利用這個標誌在他們之間進行互動。
3. 程式碼範例:用戶端類比HTTP 協議
1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net" 7 "os" 8 ) 9 10 func main() {11 service := "www.baidu.com:80"12 // tcpAddr, 將網域名稱+連接埠,解析成 ip+連接埠13 tcpAddr, err := net.ResolveTCPAddr("tcp4", service)14 fmt.Println(tcpAddr)15 checkError(err)16 conn, err := net.DialTCP("tcp", nil, tcpAddr)17 checkError(err)18 _, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))19 checkError(err)20 result, err := ioutil.ReadAll(conn)21 checkError(err)22 fmt.Println(string(result))23 }24 25 func checkError(err error) {26 if err != nil {27 fmt.Fprintf(os.Stderr, "Fatal error:%s", err.Error())28 }29 }View Code
4. 程式碼範例:TCP,用戶端與伺服器互動
/server/main.go
1 package main 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 "time" 8 ) 9 10 func main() {11 listener, err := net.Listen("tcp", "localhost:2300")12 checkError(err)13 fmt.Println("Service Starting...")14 defer listener.Close()15 for {16 conn, err := listener.Accept()17 fmt.Println("已串連:", conn.LocalAddr())18 if err != nil {19 continue20 }21 go handleClient(conn)22 }23 }24 25 func checkError(err error) {26 if err != nil {27 fmt.Fprintf(os.Stderr, "Fatal error:%s", err.Error())28 }29 }30 31 func handleClient(conn net.Conn) {32 defer conn.Close()33 daytime := time.Now().String()34 conn.Write([]byte(daytime))35 36 }View Code
/client/main.go
1 package main 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 ) 8 9 func main() {10 conn, err := net.Dial("tcp", "localhost:2300")11 checkError(err)12 bt := make([]byte, 1024)13 _, err = conn.Read(bt)14 fmt.Println(string(bt))15 defer conn.Close()16 }17 18 func checkError(err error) {19 if err != nil {20 fmt.Fprintf(os.Stderr, "Fatal error:%s", err.Error())21 }22 }View Code
5. 程式碼範例:UDP,用戶端與伺服器互動
/server/main.go
1 package main 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 "time" 8 ) 9 10 func main() {11 service := "localhost:1200"12 udpAddr, err := net.ResolveUDPAddr("udp", service)13 conn, err := net.ListenUDP("udp", udpAddr)14 checkError(err)15 fmt.Println("Starting...")16 for {17 handleClient(conn)18 }19 }20 21 func checkError(err error) {22 if err != nil {23 fmt.Fprintf(os.Stderr, "Fatal error ", err.Error())24 os.Exit(1)25 }26 }27 28 func handleClient(conn *net.UDPConn) {29 fmt.Println("接收到請求了,開始處理")30 var buf [512]byte31 _, addr, err := conn.ReadFromUDP(buf[0:])32 if err != nil {33 return34 }35 fmt.Println(string(buf[0:]))36 daytime := time.Now().String()37 conn.WriteToUDP([]byte(daytime), addr)38 }View Code
/client/main.go
1 package main 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 ) 8 9 func main() {10 service := "localhost:1200"11 udpAddr, err := net.ResolveUDPAddr("udp", service)12 checkError(err)13 conn, err := net.DialUDP("udp", nil, udpAddr)14 checkError(err)15 conn.Write([]byte("hello world"))16 var bt [512]byte17 conn.ReadFromUDP(bt[0:])18 fmt.Println(string(bt[0:]))19 defer conn.Close()20 }21 22 func checkError(err error) {23 if err != nil {24 fmt.Fprintf(os.Stderr, "Fatal error ", err.Error())25 os.Exit(1)26 }27 }View Code