go-Socket编程

1.什么是Socket

socket起源于Unix,而Unix基本哲学之一就是“一切皆文件”,都是可以用“打开open –>读写write/read–>关闭close”模式来操作。socket就是该模式的一个实现,套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。

常用的socket类型有两种:流式Socket(sock_stream)和数据报式Socket(sock_drgam)。流式是一种面向连接的socket,针对于面向连接的TCP服务;数据报式socket是一种无连接的socket,对应于无连接的UDP服务应用。

2.TCP Socket

2.1.TCP Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package client

import (
"fmt"
"io"
"net"
)

func main() {
// 校验服务器地址
tcpAddr, _ := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080")

// 连接服务器
conn, _ := net.DialTCP("tcp", nil, tcpAddr)

// 向服务器写数据
conn.Write([]byte("ping"))

// 接收服务器返回的数据
res, _ := io.ReadAll(conn)
fmt.Printf("res: %v\n", res)
}

2.2.TCP Server

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
package main

import (
"fmt"
"log"
"net"
)

func main() {
// 校验地址
tcpAddr, _ := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080")

// 启动服务,监听对应端口
listener, _ := net.ListenTCP("tcp", tcpAddr)

// 接收并处理客户端发送的数据,并返回数据
for {
conn, _ := listener.Accept()
go handleConn(conn)
}
}

func handleConn(conn net.Conn) {
// 读取客户端发送的数据
data := make([]byte, 1024)
n, err := conn.Read(data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("data: %v\n", string(data[:n]))

// 向客户端发送数据
conn.Write([]byte("pong"))

conn.Close()
}

3.UDP Socket

3.1.UDP Client

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
package main

import (
"fmt"
"net"
"time"
)

func main() {
// 校验服务器地址
udpAddr, _ := net.ResolveUDPAddr("udp4", "127.0.0.1:8080")

// 连接服务器
conn, _ := net.DialUDP("udp", nil, udpAddr)
for {
time.Sleep(time.Second * 2)
// 向服务器写数据
conn.Write([]byte("ping"))

// 接收服务器返回的数据
data := make([]byte, 1024)
conn.Read(data)
fmt.Printf("res: %v\n", string(data))
}
}

3.2.UDP Server

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
package main

import (
"fmt"
"log"
"net"
)

func main() {
// 校验地址
udpAddr, _ := net.ResolveUDPAddr("udp4", "127.0.0.1:8080")

// 启动服务,监听对应端口
conn, _ := net.ListenUDP("udp", udpAddr)

// 接收并处理客户端发送的数据,并返回数据
for {
handleUDPConn(conn)
}
}

func handleUDPConn(conn *net.UDPConn) {
// 读取客户端发送的数据
data := make([]byte, 1024)
n, udpAddr, err := conn.ReadFromUDP(data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("data: %v\n", string(data[:n]))

// 向客户端发送数据
conn.WriteToUDP([]byte("pong"), udpAddr)
}