用golang写一个聊天室
时间: 2023-08-31 11:06:32 浏览: 16
好的,我可以给你提供一个简单的聊天室代码实现。这个聊天室可以实现多个用户之间的聊天,基于 TCP 协议实现,使用了 goroutine 来处理并发。代码如下:
```go
package main
import (
"bufio"
"fmt"
"net"
"strings"
)
type client chan<- string // 一个可以向客户端发送消息的通道
var (
entering = make(chan client)
leaving = make(chan client)
messages = make(chan string) // 所有客户端共享的消息通道
)
func broadcaster() {
clients := make(map[client]bool) // 所有连接的客户端
for {
select {
case msg := <-messages:
// 把消息广播到所有客户端
for cli := range clients {
cli <- msg
}
case cli := <-entering:
// 新客户端连接
clients[cli] = true
case cli := <-leaving:
// 客户端离开
delete(clients, cli)
close(cli)
}
}
}
func handleConn(conn net.Conn) {
ch := make(chan string) // 对于每个客户端,都有一个可以向该客户端发送消息的通道
go clientWriter(conn, ch)
who := conn.RemoteAddr().String()
ch <- "You are " + who
messages <- who + " has arrived"
entering <- ch
input := bufio.NewScanner(conn)
for input.Scan() {
messages <- who + ": " + input.Text()
}
leaving <- ch
messages <- who + " has left"
conn.Close()
}
func clientWriter(conn net.Conn, ch <-chan string) {
for msg := range ch {
fmt.Fprintln(conn, msg)
}
}
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
fmt.Println(err)
return
}
defer listener.Close()
go broadcaster()
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println(err)
continue
}
go handleConn(conn)
}
}
```
上述代码中,我们定义了三个通道:
- entering:新客户端连接时,会向该通道发送一个客户端的通道,由 broadcaster() 函数处理;
- leaving:客户端离开时,会向该通道发送一个客户端的通道,由 broadcaster() 函数处理;
- messages:所有客户端共享的消息通道,由 broadcaster() 函数处理。
broadcaster() 函数会不断地监听通道,根据不同的通道,执行不同的操作,具体如下:
- 如果 messages 中有消息,则广播该消息到所有客户端;
- 如果 entering 中有客户端,将该客户端加入到 clients 中;
- 如果 leaving 中有客户端,将该客户端从 clients 中删除,并关闭该客户端的通道。
handleConn() 函数用于处理每一个客户端连接,它会创建一个用于向该客户端发送消息的通道 ch,然后向 entering 通道发送 ch,表示该客户端已连接。接着,它会监听客户端输入的消息,如果有新消息,则向 messages 通道发送该消息。
clientWriter() 函数用于将消息发送到客户端。对于每个客户端,都有一个可以向该客户端发送消息的通道 ch,该函数会不断地读取该通道,如果有新消息,则将该消息写入到客户端连接中。
最后,main() 函数会监听端口 8000,如果有新连接,则创建一个新的 goroutine 处理该连接。
相关推荐
















