Go 语言的net库真是太顶了!
今天在看go的net来着,就想顺手实现一个tcp聊天室,大致看了一下net这个库,发现它实现一个简易的tcp聊天室比使用C语言之流要简单的多
要想实现一个多人的聊天室,就得先弄明白单个客户端与服务端是如何交互的,这里我们先不使用协程来处理最简单的情况
服务端
/*
* @Author: NorthCityChen
* @LastEditTime: 2021-09-12 18:55:57
* @Description:
* @Website: https://grimoire.cn
* Copyright (c) NorthCityChen All rights reserved.
*/
package main
import (
"fmt"
"net"
)
func main() {
listener, err := net.Listen("tcp", ":3000")
// Start listening
if err != nil {
fmt.Println(err)
return
}
conn, err := listener.Accept()
// Waiting for the client to connect (blocking)
if err != nil {
fmt.Println(err)
return
}
for {
buf := make([]byte, 512)
length, err := conn.Read(buf)
// conn.read(buf) 会将从conn传来的数据传到buf数组中
if err != nil {
fmt.Println(err)
return
}
fmt.Println(length, string(buf))
// 将buf中的数据打印出来
if string(buf[:length]) == "end" {
break
}
// 似乎这里会传过来一个换行符号,需要手动给他截掉
}
err = conn.Close()
// 关闭链接 释放资源
if err != nil {
fmt.Println(err)
return
}
}
客户端
/*
* @Author: NorthCityChen
* @LastEditTime: 2021-09-12 18:36:35
* @Description:
* @Website: https://grimoire.cn
* Copyright (c) NorthCityChen All rights reserved.
*/
package main
import (
"fmt"
"net"
)
func main() {
client, err := net.Dial("tcp", "localhost:3000")
// 启动客户端并连接服务端
if err != nil {
fmt.Println(err)
return
}
defer client.Close()
client.Write([]byte("Hello world"))
// 将数据写入连接(传到服务端)
if err != nil {
fmt.Println(err)
}
}
根据上述的原理,我们可以尝试写一个支持多客户端的聊天室(代码有点简陋,若有纰漏之处还请不吝赐教)
服务端
/*
* @Author: NorthCityChen
* @LastEditTime: 2021-09-12 20:21:22
* @Description:
* @Website: https://grimoire.cn
* Copyright (c) NorthCityChen All rights reserved.
*/
package main
import (
"fmt"
"net"
)
var clients = make(map[net.Conn]bool)
var messages = make(chan []byte)
func main() {
listener, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println(err)
return
}
go boardcast()
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println(err)
continue
}
go handleConnection(conn)
}
}
// 全局广播
func boardcast() {
for msg := range messages {
for conn, _ := range clients {
if _, err := conn.Write(msg); err != nil {
fmt.Println(err)
continue
}
}
fmt.Println(msg)
}
}
func handleConnection(conn net.Conn) {
clients[conn] = true
fmt.Println("[System]:", conn.RemoteAddr().String(), "进入聊天室")
for {
buf := make([]byte, 512)
length, err := conn.Read(buf)
if err != nil {
fmt.Println(err)
break
}
messages <- buf[:length]
}
delete(clients, conn)
fmt.Println("[System]:", conn.RemoteAddr().String(), "离去...")
conn.Close()
}
客户端
/*
* @Author: NorthCityChen
* @LastEditTime: 2021-09-12 20:14:09
* @Description:
* @Website: https://grimoire.cn
* Copyright (c) NorthCityChen All rights reserved.
*/
package main
import (
"bufio"
"fmt"
"net"
"os"
)
func main() {
client, err := net.Dial("tcp", "localhost:8080")
if err != nil {
fmt.Println(err)
return
}
defer client.Close()
go func() {
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
client.Write(input.Bytes())
}
}()
for {
buf := make([]byte, 512)
length, err := client.Read(buf)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(buf[:length]))
}
}
作者:NorthCity1984
出处:https://grimoire.cn/golang/go-chatroom.html
版权:本文《Go 学习笔记:基于net库实现的聊天室》版权归作者所有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
出处:https://grimoire.cn/golang/go-chatroom.html
版权:本文《Go 学习笔记:基于net库实现的聊天室》版权归作者所有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任