聊天室的组成

聊天室分为两个部分,分别是:

  • 服务端
  • 客户端


    然后,一般情况下我们互相聊天使用的都只是客户端而已,服务端只是起到调度的作用

信息发送与接收的流程

  1. 假设我们有 服务端(S 客户端(C1 客户端(C2 客户端(C3)并且 S 已经 C1 C2 C3 建立了连接

理论上的流程是这样的:

  1. C1 向 S 发出信息
  2. S 接收到信息
  3. S 将接收到的信息广播给 C2 C3
  4. C2 C3 接收信息

服务器代码

  1. package main
  2. import (
  3. "time"
  4. "fmt"
  5. "net"
  6. )
  7. // 客户端 map
  8. var client_map = make(map[string]*net.TCPConn)
  9. // 监听请求
  10. func listen_client(ip_port string) {
  11. tcpAddr, _ := net.ResolveTCPAddr("tcp", ip_port)
  12. tcpListener, _ := net.ListenTCP("tcp", tcpAddr)
  13. for {// 不停地接收
  14. client_con, _ := tcpListener.AcceptTCP()// 监听请求连接
  15. client_map[client_con.RemoteAddr().String()] = client_con// 将连接添加到 map
  16. go add_receiver(client_con)
  17. fmt.Println("用户 : ", client_con.RemoteAddr().String(), " 已连接.")
  18. }
  19. }
  20. // 向连接添加接收器
  21. func add_receiver(current_connect *net.TCPConn) {
  22. for {
  23. byte_msg := make([]byte, 2048)
  24. len, err := current_connect.Read(byte_msg)
  25. if err != nil { current_connect.Close() }
  26. fmt.Println(string(byte_msg[:len]))
  27. msg_broadcast(byte_msg[:len], current_connect.RemoteAddr().String())
  28. }
  29. }
  30. // 广播给所有 client
  31. func msg_broadcast(byte_msg []byte, key string) {
  32. for k, con := range client_map {
  33. if k != key { con.Write(byte_msg) }
  34. }
  35. }
  36. // 主函数
  37. func main() {
  38. fmt.Println("服务已启动...")
  39. time.Sleep(1 * time.Second)
  40. fmt.Println("等待客户端请求连接...")
  41. go listen_client("127.0.0.1:1801")
  42. select{}
  43. }

客户端代码

  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. "os"
  6. "bufio"
  7. )
  8. // 用户名
  9. var login_name string
  10. // 本机连接
  11. var self_connect *net.TCPConn
  12. // 读取行文本
  13. var reader = bufio.NewReader(os.Stdin)
  14. // 建立连接
  15. func connect(addr string) {
  16. tcp_addr, _ := net.ResolveTCPAddr("tcp", addr) // 使用tcp
  17. con, err := net.DialTCP("tcp", nil, tcp_addr) // 拨号
  18. self_connect = con
  19. if err != nil {
  20. fmt.Println("服务器连接失败")
  21. os.Exit(1)
  22. }
  23. go msg_sender()
  24. go msg_receiver()
  25. }
  26. // 消息接收器
  27. func msg_receiver() {
  28. buff := make([]byte, 2048)
  29. for {
  30. len, _ := self_connect.Read(buff) // 读取消息
  31. fmt.Println(string(buff[:len]))
  32. }
  33. }
  34. // 消息发送器
  35. func msg_sender() {
  36. for {
  37. read_line_msg, _, _ := reader.ReadLine()
  38. read_line_msg = []byte(login_name + " : " + string(read_line_msg))
  39. self_connect.Write(read_line_msg)
  40. }
  41. }
  42. // 主函数
  43. func main() {
  44. fmt.Println("请问您怎么称呼?")
  45. name, _, _ := reader.ReadLine()
  46. login_name = string(name)
  47. connect("127.0.0.1:1801")
  48. select{}
  49. }

image.jpeg