go实现多聊天并发 服务端
2024-10-21 20:25:17
package main import (
"fmt"
"net"
"time"
)
type Client struct {
ch chan string //用户发送数据的管道
name string //用户名
addr string//网络地址
}
var message = make(chan string) //用来保存用户的消息
//定义一个map 值为在线的用户
var onlineClientMap map[string]Client//
func main() {
listener,err := net.Listen("tcp","127.0.0.1:8000")
if err !=nil{
fmt.Println(err)
}
defer listener.Close()
go Manager()
//主协程,循环阻塞用户连接
for{
conn, err := listener.Accept()
if err!=nil{
fmt.Println(err)
continue
}
go handleConn(conn) } }
func makeMsg(client Client,msg string)(buff string){ buff ="["+client.addr+"]"+client.name+":"+msg+"\n"
return
} func handleConn(conn net.Conn){
cliAddr:= conn.RemoteAddr().String()
defer conn.Close()
client :=Client{
make(chan string),
cliAddr,
cliAddr,
}
onlineClientMap[cliAddr] = client
//给当前客户端发送信息
go writeMsgToClient(client,conn)
//广播某个在线
message<-"I am here\n"
message<- makeMsg(client,"login")
//是否主动退出
isQuit:=make(chan bool)
hasData:= make(chan bool)
//新开一个协程接收用户发过来的数据
go func() {
buff:= make([]byte,2048)
for{
n,err :=conn.Read(buff)
fmt.Println(n)
if err!=nil{
fmt.Println(nil)
}
if n==0{
fmt.Println("断开连接")
isQuit<-true
return
}
msg := string(buff[:n-1])
if len(msg)==3&& msg =="who"{
for _,tmp := range onlineClientMap{
msg = tmp.addr+":"+tmp.name+"\n"
conn.Write([]byte(msg)) }
}else{
message<-makeMsg(client,msg)
}
hasData<-true
}
}()
for{
select { case <-isQuit:
delete(onlineClientMap,cliAddr)//当前用户从map移除
message<-makeMsg(client,"login out")//广播退出
return
case <-hasData: case <-time.After(60*time.Second):
delete(onlineClientMap,cliAddr)//当前用户从map移除
message<-makeMsg(client,"time out")//广播退出
return
} } }
func Manager() {
onlineClientMap = make(map[string]Client)//给map分配空间
for{
msg := <-message
for _ ,client :=range onlineClientMap{
client.ch<-msg }
}
} func writeMsgToClient(client Client,conn net.Conn) {
for msg:= range client.ch{
conn.Write([]byte(msg))
} }
最新文章
- iOS 检测状态栏点击事件
- LED BIN code
- Alice and Bob 要用到辗转相减
- [双连通分量] POJ 3694 Network
- JDSideMenu实现(整块)侧滑功能,主视图会和状态栏(StatusBar)会一起滑动。
- 打开U盘后文件都不见了的解决方法
- iso定制封装
- 国内IT技术博客对比
- spring 源码之IOC 类图
- ASP.NET MVC:01理解MVC模式
- SICP 习题(1.1,1.2,1.3,1.4)解题总结。
- [COGS 1752] 摩基亚Mokia
- 14 fragment传值
- C++中const加强
- cpp typename关键字
- SQL SERVER 游标循环读取表数据
- zoj4110 Strings in the Pocket(manacher)
- 详解javascript中this的工作原理
- linux下修改mysql登录密码
- Css的向左浮动、先右浮动、绝对定位、相对定位的简单使用