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 }
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 continue 20 } 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 }
/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 }
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]byte 31 _, addr, err := conn.ReadFromUDP(buf[0:]) 32 if err != nil { 33 return 34 } 35 fmt.Println(string(buf[0:])) 36 daytime := time.Now().String() 37 conn.WriteToUDP([]byte(daytime), addr) 38 }
/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]byte 17 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 }
有疑问加站长微信联系(非本文作者)