【Golang】✔️实战✔️ 聊天室 ☢️建议手收藏☢️

网友投稿 591 2022-05-29

golang】✔️实战✔️ 聊天室 ☢️建议手☢️

概述

服务端实现

客户端实现

日志

概述

今天我们会结合之前几节课的知识来综合实战一下, 实现一个聊天室.

服务端实现

运行的时候我们可以开启一个服务端和 N 个客户端, 来实现聊天室.

代码:

package main import ( "fmt" "log" "net" "os" "strings" "time" ) // ================常量================ const ( // 日志路径 log_path = "chat_room/" ) // ===============全局变量============== // 文件日志 var logFile *os.File // 日志类 var logger *log.Logger // 客户端连接, key: ip端口, value: 连接对象 var onlineConns = make(map[string]net.Conn) // 消息队列, 缓冲区 var message_quene = make(chan string, 1024) // 消息, 处理程序退出 var quitchan = make(chan bool) // 消息协程 func comsume_msg() { for { select { // 取出消息 case msg := <- message_quene: process_msg(msg) // 处理退出 case <- quitchan: break } } } // 消息解析协程 func process_msg(message string) { // 字符串切割 contents := strings.Split(message, "#") if len(contents) > 1 { // 取出地址 address := contents[0] // 取出消息 message := contents[1] // 删除首尾 address = strings.Trim(address, " ") // 在线连接 conn, ok := onlineConns[address] if ok { _, err := conn.Write([]byte(message)) fmt.Println("发送消息:", message, "目的地:", address) if err != nil { fmt.Println("在线连接发送失败") } } } else { // 查看list contents = strings.Split(message, "&") if contents[1] == "list" { var str = "" // 向每个客户端发送信息 for i := range onlineConns { // str += "||||" + i } // 在线连接 conn, ok := onlineConns[contents[0]] if ok { _, err := conn.Write([]byte(str)) if err != nil { fmt.Println("在线发送失败:", err) } } fmt.Println("发送消息:", str, "目的地:", conn.RemoteAddr()) logger.Println("发送消息:", str, "目的地:", conn.RemoteAddr()) } } } // 接收消息 func receive_info(conn net.Conn) { // 缓冲 buffer := make([]byte, 1024) // 循环读取 for { // 读取数据 nums, err := conn.Read(buffer) if err != nil { break } if nums != 0 { // 获取地址 address := conn.RemoteAddr() // 获取消息 message := string(buffer[:nums]) // 调试输出 fmt.Println("收到消息:", message, "来自:", address) logger.Println("收到消息:", message, "来自:", address) // 处理客户端退出 if message == "exit" { // 调试输出 fmt.Println("客户端:", conn.RemoteAddr(), "正在退出...") logger.Println("客户端:", conn.RemoteAddr(), "正在退出...") // 退出 client_exit(conn) } else{ // 消息队列存储消息 message_quene <- message } } } } // 处理退出 func client_exit(conn net.Conn) { // 获取地址 address := fmt.Sprint(conn.RemoteAddr()) // 客户端退出时, 从map中移除地址 delete(onlineConns, address) // 关闭连接 conn.Close() // 输出当前列表 fmt.Println("客户端列表:\n--------------------") logger.Println("客户端列表:\n--------------------") for i := range onlineConns { fmt.Println(i) } } // 错误处理 func error_check(err error) { if err != nil { fmt.Println("Error:", err) os.Exit(1) } } func main() { fmt.Println("服务端正在启动...") // 打开日志文件 name := fmt.Sprintf("%d_%02d_%02d_%02d_%02d_%02d_server.log", time.Now().Year(), time.Now().Month(), time.Now().Day(), time.Now().Hour(), time.Now().Minute(), time.Now().Second(), ) log_file, err := os.OpenFile((log_path + name), os.O_RDWR | os.O_CREATE, 0) if err != nil { fmt.Println("日志文件打开失败:", err.Error()) os.Exit(-1) } // 关闭 defer log_file.Close() // 创建一个日志对象 logger = log.New(log_file, "\r\n", log.Ldate | log.Ltime | log.Llongfile) logger.Println("写入日志, 服务器正在启动...") // 创建TCP服务端 listen_socket, err := net.Listen("tcp", "127.0.0.1:8888") error_check(err) // 关闭 defer listen_socket.Close() fmt.Println("服务端启动完毕, 等待连接...") // 协程 go comsume_msg() // 启动连接 for { // 连接新客户端 conn, err := listen_socket.Accept() error_check(err) fmt.Println("服务端连接到客服端, 客户端地址:", conn.RemoteAddr()) logger.Println("服务端连接到客服端, 客户端地址:", conn.RemoteAddr()) // 获取地址 address := fmt.Sprint(conn.RemoteAddr()) // 添加到全局变量 onlineConns[address] = conn // 遍历每一个连接 fmt.Println("客户端列表:\n--------------------") logger.Println("客户端列表:\n---------------------------------------------------") for i := range onlineConns { fmt.Println(i) logger.Println(i) } // 发送消息 go receive_info(conn) } }

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

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

【Golang】✔️实战✔️ 聊天室 ☢️建议手收藏☢️

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

客户端实现

package main import ( "bufio" "fmt" "net" "os" ) // 发送消息 func send_msg(conn net.Conn) { // 循环发送 for { // 读取键盘输入 reader := bufio.NewReader(os.Stdin) // 读取一行 data, _, _ := reader.ReadLine() // 发送输入的字符串 _, err := conn.Write(data) fmt.Println("发送消息:", string(data)) if err != nil { conn.Close() fmt.Println("Error:", err, "客户端关闭") os.Exit(0) } // 收到exit, 关闭客户端 if string(data) == "exit" { fmt.Println("客户端关闭") os.Exit(0) } } } func main() { fmt.Println("客服端正在建立连接...") // 建立网络连接 conn, err := net.Dial("tcp", "127.0.0.1:8888") if err != nil { fmt.Println("网络连接错误") os.Exit(1) } fmt.Println("客户端成功连接到服务端, 服务端地址:", conn.RemoteAddr()) // 发送消息 go send_msg(conn) // 接收消息 buffer := make([]byte, 1024) // 循环接收 for { // 读取消息 nums, err := conn.Read(buffer) if err != nil { fmt.Println("读取消息出错, 退出客户端") os.Exit(0) } fmt.Println("收到消息:", string(buffer[:nums])) } }

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

输出结果:

server:

服务端正在启动... 服务端启动完毕, 等待连接... 服务端连接到客服端, 客户端地址: 127.0.0.1:63776 客户端列表: -------------------- 127.0.0.1:63776 服务端连接到客服端, 客户端地址: 127.0.0.1:63777 客户端列表: -------------------- 127.0.0.1:63776 127.0.0.1:63777 收到消息: 127.0.0.1:63776&list 来自: 127.0.0.1:63776 发送消息: ||||127.0.0.1:63776||||127.0.0.1:63777 目的地: 127.0.0.1:63776 收到消息: 127.0.0.1:63777#hi, client2 来自: 127.0.0.1:63776 发送消息: hi, client2 目的地: 127.0.0.1:63777 收到消息: 127.0.0.1:63777&list 来自: 127.0.0.1:63777 发送消息: ||||127.0.0.1:63776||||127.0.0.1:63777 目的地: 127.0.0.1:63777 收到消息: 127.0.0.1:63776#hi, client1 来自: 127.0.0.1:63777 发送消息: hi, client1 目的地: 127.0.0.1:63776 收到消息: exit 来自: 127.0.0.1:63776 客户端: 127.0.0.1:63776 正在退出... 客户端列表: -------------------- 127.0.0.1:63777 收到消息: exit 来自: 127.0.0.1:63777 客户端: 127.0.0.1:63777 正在退出... 客户端列表: --------------------

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

client1:

客服端正在建立连接... 客户端成功连接到服务端, 服务端地址: 127.0.0.1:8888 127.0.0.1:63776&list 发送消息: 127.0.0.1:63776&list 收到消息: ||||127.0.0.1:63776||||127.0.0.1:63777 127.0.0.1:63777#hi, client2 发送消息: 127.0.0.1:63777#hi, client2 收到消息: hi, client1 exit 发送消息: exit 客户端关闭

1

2

3

4

5

6

7

8

9

10

11

client2:

客服端正在建立连接... 客户端成功连接到服务端, 服务端地址: 127.0.0.1:8888 收到消息: hi, client2 127.0.0.1:63777&list 发送消息: 127.0.0.1:63777&list 收到消息: ||||127.0.0.1:63776||||127.0.0.1:63777 127.0.0.1:63776#hi, client1 发送消息: 127.0.0.1:63776#hi, client1 exit 发送消息: exit 客户端关闭

1

2

3

4

5

6

7

8

9

10

11

日志

2021/08/27 01:08:04 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:209: 写入日志, 服务器正在启动... 2021/08/27 01:08:07 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:231: 服务端连接到客服端, 客户端地址: 127.0.0.1:63776 2021/08/27 01:08:07 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:242: 客户端列表: --------------------------------------------------- 2021/08/27 01:08:07 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:245: 127.0.0.1:63776 2021/08/27 01:08:09 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:231: 服务端连接到客服端, 客户端地址: 127.0.0.1:63777 2021/08/27 01:08:09 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:242: 客户端列表: --------------------------------------------------- 2021/08/27 01:08:09 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:245: 127.0.0.1:63776 2021/08/27 01:08:09 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:245: 127.0.0.1:63777 2021/08/27 01:08:20 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:135: 收到消息: 127.0.0.1:63776&list 来自: 127.0.0.1:63776 2021/08/27 01:08:20 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:104: 发送消息: ||||127.0.0.1:63776||||127.0.0.1:63777 目的地: 127.0.0.1:63776 2021/08/27 01:08:31 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:135: 收到消息: 127.0.0.1:63777#hi, client2 来自: 127.0.0.1:63776 2021/08/27 01:08:42 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:135: 收到消息: 127.0.0.1:63777&list 来自: 127.0.0.1:63777 2021/08/27 01:08:42 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:104: 发送消息: ||||127.0.0.1:63776||||127.0.0.1:63777 目的地: 127.0.0.1:63777 2021/08/27 01:08:53 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:135: 收到消息: 127.0.0.1:63776#hi, client1 来自: 127.0.0.1:63777 2021/08/27 01:09:04 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:135: 收到消息: exit 来自: 127.0.0.1:63776 2021/08/27 01:09:04 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:142: 客户端: 127.0.0.1:63776 正在退出... 2021/08/27 01:09:04 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:168: 客户端列表: -------------------- 2021/08/27 01:09:11 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:135: 收到消息: exit 来自: 127.0.0.1:63777 2021/08/27 01:09:11 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:142: 客户端: 127.0.0.1:63777 正在退出... 2021/08/27 01:09:11 C:/Users/Windows/Desktop/project2/chat_room/server2/server.go:168: 客户端列表: --------------------

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

客服

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:【python实战】女友半夜加班发自拍 python男友用30行代码发现惊天秘密
下一篇:计算机专业的学生怎么可以连计算机发展史都不知道
相关文章