×

利用chan与go做简陋聊天室-GOLANG

96
与子笑
2018.05.20 10:34 字数 466

golang  @amazeUI  2018-04-08 17:45:07


源码来自go语言圣经。

这里自己做了注释,写出了自己的理解。

type client chan<- string  // send only channel

var (

entering = make(chan client)

leaving = make(chan client)

messages = make(chan string)

)

func main() {

listener,err := net.Listen("tcp","0.0.0.0:8888")

if err != nil {

log.Fatal(err)

}

go broadcaster()//单独起一个go开始广播监听(异步,函数内部不停的select监听各类消息)

  for{//这里不停的监听新链接

     conn,err := listener.Accept()

if err != nil {

fmt.Fprintf(os.Stdout,"you got something wrong %v",err)

continue

     }

go handleConn(conn)//监听每一个链接上来的链接交由handleconn处理

  }

}

func broadcaster() {

clients := make(map[client]bool)//all connected clients

  for {

select {

case msg := <- messages:

for cli := range clients{

cli <- msg

        }

case cli := <- entering:

clients[cli]= true//将新加入的链接存到clients里

     case cli := <- leaving:

delete(clients,cli)

close(cli)

}

}

}

func handleConn(conn net.Conn) {//每个客户端保证一个handleconn

  ch := make(chan string)

go clientWriter(conn,ch)

who := conn.RemoteAddr().String()

ch <- "You are " + who

  messages <- who + " has joined us"//只要一有消息来就存到全局变量messages里面去开始广播欢迎消息

  entering <- ch//将新chan存入entering这个特殊结构中

  input := bufio.NewScanner(conn)

for input.Scan() {//这里不停的接受该链接用户传递过来的消息

     messages <- who + ": " + input.Text()//再次存入客户端输入的消息文本,广播函数再次收到信号

  }

leaving <- ch//如果客户端关闭了标准输入,那么把队列离开写入leaving交给广播函数去删除这个客户端并关闭这个客户端。

//广播这个人的离开给所有人。

  messages <- who + " has left "

  conn.Close()

}

func clientWriter(conn net.Conn,ch <-chan string) {

for msg := range ch {

fmt.Fprintln(conn,msg)// NOTE: ignoring network errors

  }

}

PHP01.COM
Web note ad 1