golang实现聊天服务器

397 阅读1分钟
package main

import (
   "bufio"
   "fmt"
   "log"
   "net"
)

/*
简单聊天室需求分析:

   因为是即时通信,所有使用同步通道

   需要广播群聊消息到各个客户端:
      1. 所有需要将所有客户端进行统一管理
         1) 删除一个离开的用户
         2) 加入一个刚来的用户
      2. 对一个客户端消息进行群发(包括发给自己)
         1)直接遍历发送就行了

   对接客户端协程要做的事情:
      1. 写入信息
      2. 断开连接时,关闭连接
*/

func main() {
   //创建服务端
   listener, err := net.Listen("tcp", "localhost:8080")
   if err != nil {
      log.Fatal(err)
   }
   //开启信息广播,连接管理
   go broadcaster()
   for {
      conn, err := listener.Accept()
      if err != nil {
         log.Println(err)
         continue
      }
      go handleConn(conn)
   }
}
func handleConn(conn net.Conn) {
   //对进来的人员进行欢迎
   who := conn.RemoteAddr().String()
   messages <- "欢迎:" + who + " 加入群聊!"

   client := make(chan string)
   enter <- client
   //对客户端进行信息进行会写
   go func() {
      for msg := range client {
         fmt.Println(msg)
         fmt.Fprintf(conn, "%s\n", msg)
      }
   }()
   //接收客户端发来的信息,并进行广播
   input := bufio.NewScanner(conn)
   for input.Scan() {
      messages <- who + ": " + input.Text()
   }
   leave <- client
   conn.Close()

   //对人员的离开进行通知
   messages <- who + " 退出了群聊!"
}

type client chan<- string

var (
   messages = make(chan string)
   enter    = make(chan client)
   leave    = make(chan client)
)

func broadcaster() {
   clients := make(map[client]bool)
   for {
      select {
      case msg := <-messages:
         for client, _ := range clients {
            client <- msg
         }
      case client := <-enter:
         clients[client] = true
      case client := <-leave:
         delete(clients, client)
         close(client)
      }
   }
}

我们在cmd窗口进行测试:我使用的是 telnet 127.0.0.1 8080 这个telnet要是使用不了,可以百度一下!