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))
} }

最新文章

  1. iOS 检测状态栏点击事件
  2. LED BIN code
  3. Alice and Bob 要用到辗转相减
  4. [双连通分量] POJ 3694 Network
  5. JDSideMenu实现(整块)侧滑功能,主视图会和状态栏(StatusBar)会一起滑动。
  6. 打开U盘后文件都不见了的解决方法
  7. iso定制封装
  8. 国内IT技术博客对比
  9. spring 源码之IOC 类图
  10. ASP.NET MVC:01理解MVC模式
  11. SICP 习题(1.1,1.2,1.3,1.4)解题总结。
  12. [COGS 1752] 摩基亚Mokia
  13. 14 fragment传值
  14. C++中const加强
  15. cpp typename关键字
  16. SQL SERVER 游标循环读取表数据
  17. zoj4110 Strings in the Pocket(manacher)
  18. 详解javascript中this的工作原理
  19. linux下修改mysql登录密码
  20. Css的向左浮动、先右浮动、绝对定位、相对定位的简单使用

热门文章

  1. hashMap常见问题
  2. markdown ——flow流程图
  3. 程序员生存之道,多写bug!
  4. 【IDEA使用技巧】(1) —— 快捷键
  5. docker-compose命令使用说明
  6. Hadoop 系列(五)—— Hadoop 集群环境搭建
  7. Windows中的消息与消息队列
  8. JNA的应用
  9. ① Python3.0基础语法
  10. Java调用WebService方法总结(4)--Axis调用WebService