golang练手小项目系列(4)-网络聊天室

问题描述:实现一个网络聊天室服务端。完成之后你将熟悉select、net库、time定时器的用法。要点:用户发来的消息广播给所有接入聊天室的用户。新用户进入的时候能收到聊天室所有其他用户的名字列表。使用netcat工具作为客户端。拓展:当用户不活跃的时间超过指定时间后,断开用户的连接。代码:import ( "bufio" "fmt" "log" ...
摘要由CSDN通过智能技术生成

问题描述:
实现一个网络聊天室服务端。完成之后你将熟悉select、net库、time定时器的用法。

要点:

  • 用户发来的消息广播给所有接入聊天室的用户。
  • 新用户进入的时候能收到聊天室所有其他用户的名字列表。
  • 使用netcat工具作为客户端。

拓展:

  • 当用户不活跃的时间超过指定时间后,断开用户的连接。

代码:

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

type client struct {
   Out  chan<- string
   Name string
}

var (
   entering = make(chan client)
   leaving = make(chan client)
   messages = make(chan string)
)

var timeout = 10 * time.Second

func broadcaster()  {
   clients := make(map[client] bool)

   for {
      select {
      case msg := <-messages:
         for cli := range clients {
            cli.Out <- msg
         }

      case cli := <-entering:
         clients[cli] = true

         cli.Out <- "Present:"
         for c := range clients {
            cli.Out <- c.Name
         }

      case cli := <-leaving:
         delete(clients, cli)
         close(cli.Out)
      }
   }
}


func handleConn(conn net.Conn){
   out := make(chan string, 10)
   go clientWriter(conn, out)

   in := make(chan string)
   go clientReader(conn, in)

   var who string

   var nameTimer = time.NewTimer(timeout)

   out <- "Enter your name:"

   select {
   case name := <-in:
      who = name
   case <-nameTimer.C:
      conn.Close()
      return
   }

   cli := client{out, who}

   out <- "You are " + who

   messages <- who + " has arrived"

   entering <- cli

   idle := time.NewTimer(timeout)

Loop:
   for {
      select {
      case msg := <-in:
         messages <- who + ": " + msg
         idle.Reset(timeout)
      case <-idle.C:
         conn.Close()
         break Loop
      }
   }

   leaving <- cli

   messages <- who + " has left"
   conn.Close()
}

func clientWriter(conn net.Conn, ch <-chan string)  {
   for msg := range ch{
      fmt.Fprintln(conn, msg)
   }
}

func clientReader(conn net.Conn, ch chan<- string) {
   input := bufio.NewScanner(conn)
   for input.Scan() {
      ch <- input.Text()
   }
}

func main() {

   listener, err := net.Listen("tcp", "localhost:8088")

   if err != nil{
      log.Fatal(err)
   }

   go broadcaster()

   for {
      conn, err := listener.Accept()

      if err != nil{
         log.Print(err)
         continue
      }

      go handleConn(conn)
   }

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值