标签:退出 内容 技术分享 hasd 遍历 [1] image 获取 sda

package main
import (
"net"
"fmt"
"strings"
"time"
)
type client struct {
C chan string //用户发送数据的管道
Name string //用户名
Addr string //网络地址
}
//保存在线用户
var onlineMap map[string]client
var message=make(chan string)
//新开一个协程,转发消息,每当有消息过来,遍历map,给map的每个成员发送消息
func Manager(){
//给map分配空间
onlineMap = make(map[string]client)
for {
msg:=<-message//没有消息前,会阻塞
//遍历map给每个map成员发送消息
for _,cli:= range onlineMap{
cli.C <- msg
}
}
}
//专门用于广播某人上线
func MakeMsg(cli client,msg string)(buf string){
return cli.Addr+msg
}
func WriteMsgToClient(cli client,conn net.Conn) {
for msg:=range cli.C{//给当前客户端发送信息
conn.Write([]byte(msg+"\n"))
}
}
func HandlerConn(conn net.Conn){
//处理用户连接
defer conn.Close()
//获取客户端的网络地址
cliAddr:=conn.RemoteAddr().String()
//创建一个结构体,默认用户名和网络地址一样
cli:=client{C:make(chan string),Name:cliAddr,Addr:cliAddr}
//将该结构体添加到map成员当中
onlineMap[cliAddr]=cli
//新开一个协程,专门给当前客户端发送信息
go WriteMsgToClient(cli,conn)
//广播某人上线了
message <- MakeMsg(cli,"上线了")
//提示,我是谁
cli.C<- "我是"+cli.Addr+",我上线了"
//用户是否主动推出
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("conn.Read error,err=", err)
return
}
//window上会出现空格,因此把空格给去掉
msg := []byte(strings.TrimSpace(string(buf[:n])))
// 如果用户输入who,提示当前有哪些用户在线
if string(msg)=="who"{
//遍历map,给当前用户发送所有成员
for _,tem:=range onlineMap{
user_info:=tem.Addr+":"+tem.Name+"\n"
conn.Write([]byte(user_info))
}
}else if strings.Contains(string(msg),"rename|") && len(string(msg))>=8{
//让用户重新选择用户名
//rename|satori
name:=strings.Split(string(msg),"|")[1]
cli.Name=name
onlineMap[cliAddr]=cli
//提示用户改名成功
conn.Write([]byte("修改成功,您的名字已变为"+cli.Name+"\n"))
}else{
//转发此内容
message <- MakeMsg(cli, string(msg))
}
hasData<-true
}
}()
for {
//通过select检测channel的流动
select{
case <- isQuit:
delete(onlineMap,cliAddr)//将推出的用户从onlineMap当中移除
message<-MakeMsg(cli,"下线了")//广播某个人下线了
return
case <- hasData:
case <- time.After(10*time.Second): //超过10s不发言,会强制移除
delete(onlineMap,cliAddr) //将当前用户从map中移除
message<- MakeMsg(cli,"因为长时间未发言,已强制移除")//广播谁下线了
return
}
}
}
func main(){
//监听
listener,err:=net.Listen("tcp","192.168.1.35:8000")
if err!=nil{
fmt.Println("listen error,err=",err)
return
}
//关闭连接
defer listener.Close()
//新开一个协程,转发消息,每当有消息过来,遍历map,给map的每个成员发送消息
go Manager()
//主协程,循环阻塞等待用户连接
for{
conn,err:=listener.Accept()
if err!=nil{
fmt.Println("accept error,err=",err)
continue//出现错误,进行continue,处理下一个链接
}
go HandlerConn(conn)//处理用户连接
}
}
标签:退出 内容 技术分享 hasd 遍历 [1] image 获取 sda
原文地址:https://www.cnblogs.com/traditional/p/9195838.html