Eli's Blog

1. 网络编程

1
2
3
4
5
6
7
net.Listen(network, address string) (Listener, error)
listener.Accept() (Conn, err)
conn.Close()
conn.Read([]byte) (int, err)
conn.Write([]byte)

net.Dial(network, address string) (Conn, error)

1.1 服务器

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
37
38
39
40
41
42
43
44
45
46
func main() {
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Server has started, listening on %s\n", ln.Addr())

defer ln.Close()

for {
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
continue
}

handleConnect(conn)
}
}

func handleConnect(conn net.Conn) {
defer conn.Close()

remoteAddr := conn.RemoteAddr()
fmt.Printf("[%s] connected\n", remoteAddr)

for {
buf := make([]byte, 2048)
n, err := conn.Read(buf)
if err != nil {
fmt.Printf("[%s] disconnected\n", remoteAddr)
break
}

str := string(buf[:n-1])
if str == "quit" || str == "exit" {
fmt.Printf("[%s] disconnected\n", remoteAddr)
break
}

fmt.Printf("%s >> %s\n", remoteAddr, str)

conn.Write([]byte(strings.ToUpper(str + "\n")))
}
}

1.2 客户端

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
func main() {
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
fmt.Println(err)
return
}

defer conn.Close()

// 键盘输入,并发送给服务器
go func() {
buf := make([]byte, 1024)
for {
n, err := os.Stdin.Read(buf)
if err != nil {
fmt.Println(err)
break
}

conn.Write(buf[:n])
}
}()

// 处理服务器返回数据
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf)
if err == io.EOF {
return
}
fmt.Println(string(buf[:n-1]))
}
}

2. 文件发送与接收

2.1 服务器

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
func main() {
// 开启服务
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println(err)
return
}
defer ln.Close()

fmt.Printf("[%s]等待接收文件...\n", ln.Addr())

// 接收请求
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
return
}
defer conn.Close()

// 获取对方发送的文件名
buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
fmt.Println(err)
return
}
fileName := string(buf[:n])
fmt.Printf("文件名: [%s]\n", fileName)

// 通知对方发送文件内容
_, err = conn.Write([]byte("ok"))
if err != nil {
fmt.Println(err)
return
}

// 接收文件内容
recvFile(fileName, conn)
}

func recvFile(fileName string, conn net.Conn) {
// 创建文件
f, err := os.Create(fileName)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()

buf := make([]byte, 1024*4)
for {
n, err := conn.Read(buf)
if err != nil {
if err == io.EOF {
fmt.Println("\n文件接收完毕")
} else {
fmt.Println(err)
}
break
}

if n == 0 {
fmt.Println("文件接收完毕")
break
}

fmt.Printf(".")
_, err = f.Write(buf[:n])
if err != nil {
fmt.Println("写文件失败")
}
}
}

2.2 客户端

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
func main() {
fmt.Printf("请输入文件名: ")
var fileName string
fmt.Scan(&fileName)

// 获取文件信息
info, err := os.Stat(fileName)
if err != nil {
fmt.Println(err)
return
}

// 连接文件接收服务器
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
fmt.Println(err)
return
}
defer conn.Close()

// 发送文件名
_, err = conn.Write([]byte(info.Name()))

// 服务器是否就绪
buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
fmt.Println(err)
return
}

if "ok" != string(buf[:n]) {
fmt.Println("服务器未就绪")
return
}

// 发送文件内容
sendFile(fileName, conn)
}

func sendFile(fileName string, conn net.Conn) {
f, err := os.Open(fileName)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()

buf := make([]byte, 1024*4)
for {
_, err = f.Read(buf)
if err != nil {
if err == io.EOF {
fmt.Println("发送完毕")
} else {
fmt.Println(err)
}
break
}

// 发送内容
conn.Write(buf)
}
}

3. 聊天服务器

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
func main() {
// 开启监听服务
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println(err)
return
}
defer ln.Close()

// 转发消息
go Manager()

// 主协程,循环阻塞等待用户连接
for {
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
continue
}

go HandleConn(conn)
}
}

// 客户端
type Client struct {
C chan string
Name string
Addr string
}

// 在线用户
var onlineMap map[string]Client

// 消息
var message = make(chan string)

// 消息转发
func Manager() {
// 在线用户分配空间
onlineMap = make(map[string]Client)

for {
msg := <-message

for _, cli := range onlineMap {
cli.C <- msg
}
}
}

func HandleConn(conn net.Conn) {
defer conn.Close()

// 客户端地址
cliAddr := conn.RemoteAddr().String()

// 客户端
cli := Client{
make(chan string),
cliAddr,
cliAddr,
}

// 添加到在线用户
onlineMap[cliAddr] = cli

// 新开协程,专门给当前客户端发送信息
go WriteMsgToClient(cli, conn)

// 广播在线
message <- MakeMsg(cli, "online")

// 当前用户是否已退出
isQuit := make(chan bool)

// 当前用户是否超时
hasData := make(chan bool)

// 新开协程,接收用户发来的数据
go func() {
buf := make([]byte, 2048)

for {
n, err := conn.Read(buf)
if n == 0 {
isQuit <- true
fmt.Println("用户断开连接或出现其他问题", err)
return
}

msg := string(buf[:n-1])

// 查询当前在线用户列表
if msg == "who" {
// 给当前用户发送所有在线成员
conn.Write([]byte("user list:\n"))
for _, u := range onlineMap {
conn.Write([]byte(u.Addr + ": " + u.Name + "\n"))
}
} else if len(msg) > 8 && msg[:6] == "rename" {
name := msg[7:]
cli.Name = name
onlineMap[cliAddr] = cli
conn.Write([]byte("rename ok\n"))
} else {
// 转发内容至其他在线用户
message <- MakeMsg(cli, msg)
}

hasData <- true
}

}()

for {
select {
case <-isQuit:
// 从在线用户列表中删除
delete(onlineMap, cliAddr)

// 发送广播通知
message <- MakeMsg(cli, "offline")

return

case <-hasData:

case <-time.After(time.Second * 60):
delete(onlineMap, cliAddr)
message <- MakeMsg(cli, "timeout")
return
}
}
}

func WriteMsgToClient(cli Client, conn net.Conn) {
for msg := range cli.C {
conn.Write([]byte(msg + "\n"))
}
}

func MakeMsg(cli Client, msg string) string {
return "[" + cli.Addr + "]" + cli.Name + ": " + msg
}

4. HTTP服务器

4.1 服务器

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
func main() {
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println(err)
return
}
defer ln.Close()

fmt.Println("http://localhost:8080")

for {
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
continue
}

go handleConn(conn)
}
}

func handleConn(conn net.Conn) {
defer conn.Close()

buf := make([]byte, 1024*4)
n, err := conn.Read(buf)
if err != nil {
fmt.Println(err)
return
}

fmt.Printf("%v\n", string(buf[:n]))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func main() {
// 注册处理函数
http.HandleFunc("/go", myHandler)

fmt.Println("http://localhost:8080")
http.ListenAndServe(":8080", nil)
}

func myHandler(w http.ResponseWriter, req *http.Request) {
fmt.Println("Method:", req.Method)
fmt.Println("Header:", req.Header)
fmt.Println("RemoteAddr:", req.RemoteAddr)
fmt.Println("URL:", req.URL)

fmt.Fprintln(w, "Hello world!")
}

4.2 客户端

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

func main() {
conn, err := net.Dial("tcp", ":8080")
if err != nil {
fmt.Println(err)
return
}
defer conn.Close()

requestHead := "GET /go HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7\r\n\r\n"

fmt.Println(requestHead)
// 发送请求
conn.Write([]byte(requestHead))

// 接收响应
buf := make([]byte, 1024*4)
n, err := conn.Read(buf)
if n == 0 {
fmt.Println(err)
return
}

fmt.Printf("#%v#\n", string(buf[:n]))
}
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
func main() {
//resp, err := http.Get("http://www.baidu.com")
resp, err := http.Get("http://localhost:8080/go")
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()

fmt.Println("Status =", resp.Status)
fmt.Println("StatusCode =", resp.StatusCode)
fmt.Println("Header =", resp.Header)
//fmt.Println("Body = ", resp.Body)

var text string
buf := make([]byte, 1024*4)
for {
n, err := resp.Body.Read(buf)
if n == 0 {
fmt.Println(err)
break
}

text += string(buf[:n])
}

fmt.Println(text)
}