1. Socket 简介
常用的 Socket 类型有两种:流式 Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。
流式是一种面向连接的 Socket,针对于面向连接的 TCP 服务应用;
数据报式 Socket 是一种无连接的 Socket,对应于无连接的 UDP 服务应用
2. 网络中的进程之间如何通过 Socket 通信呢?
网络层的“ip 地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。这样利用 三元组(ip 地址,协议,端口)就可以标识网络的进程了,网络中需要互相通信的进程,就可以利用这个标志在他们之间进行交互。
3. 代码示例:客户端模拟HTTP 协议
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 }