zoukankan      html  css  js  c++  java
  • golang简易版聊天室

    功能需求:

    创建一个聊天室,实现群聊和单聊的功能,直接输入为群聊,@某人后输入为单聊

    效果图:

    群聊:

     

    单聊:

    服务端:

    package main
    
    import (
        "fmt"
        "net"
        "strings"
    )
    
    type info struct {
        conn net.Conn
        name string
    }
    
    var ch_all chan string = make(chan string)
    var ch_one chan string = make(chan string)
    var ch_who chan string = make(chan string)
    var infos map[string]info = make(map[string]info)
    
    func handle(conn net.Conn) {
        defer conn.Close()
    
        buf := make([]byte, 100)
        n, _ := conn.Read(buf)
        name := string(buf[:n])
        var oneinfo info
        oneinfo.conn = conn
        oneinfo.name = name
        addr := conn.RemoteAddr().String()
        infos[addr] = oneinfo
        msg := name + "进入聊天室"
        ch_all <- msg
    
        for {
            n, _ := conn.Read(buf)
            if n == 0 {
                fmt.Printf("%s断开连接
    ", addr)
                msg = name + "离开聊天室"
                delete(infos, addr)
                ch_all <- msg
                fmt.Println(msg)
                return
            }
            if string(buf[:n])[0] == '@' {
                sli := strings.Fields(string(buf[1:n])) //隔开
                who := sli[0]
                msg = strings.Join(sli[1:], "") //后边的再拼接回去
                ch_who <- who
                ch_one <- name + "->me : " + msg //单发
                continue
            }
            ch_all <- name + "->all : " + string(buf[:n]) //群发
        }
    }
    
    func sendone() {
        for {
            who := <-ch_who
            msg := <-ch_one
            for _, v := range infos {
                if v.name == who {
                    v.conn.Write([]byte(msg))
                    break
                }
            }
        }
    }
    func sendall() {
        for {
            msg := <-ch_all
            for _, val := range infos {
                val.conn.Write([]byte(msg))
            }
        }
    }
    func main() {
        listener, _ := net.Listen("tcp", ":9009")
        defer listener.Close()
        go sendall()
        go sendone()
        for {
            conn, _ := listener.Accept()
            fmt.Printf("%s建立连接
    ", conn.RemoteAddr().String())
            go handle(conn)
        }
    }

    客户端:

    package main
    
    import (
        "bufio"
        "fmt"
        "net"
        "os"
    )
    
    func scandata(conn net.Conn) {
        for {
            //设置可以读取带空格的myscan
            myscan := bufio.NewReader(os.Stdin)
            buf, _, _ := myscan.ReadLine()
            if string(buf) == "q" {
                os.Exit(0)
            }
            conn.Write(buf)
        }
    }
    func main() {
        conn, _ := net.Dial("tcp", "127.0.0.1:9009")
        buf := make([]byte, 1024)
        args := os.Args
        conn.Write([]byte(args[1]))
        go scandata(conn)
        for {
            n, _ := conn.Read(buf)
            fmt.Println(string(buf[:n]))
        }
    }
  • 相关阅读:
    SQL code for the partitoned example
    去掉重复的列名.txt
    末公开的存储过程.txt
    LauncherClass
    Retina时代的前端视觉优化
    获得数据库中表字段的名字.txt
    StaticConstructor.cs
    UNION ALL实现的分级汇总示例.sql
    SignAndSeal
    在现有数据库上还原时的数据文件处理示例.sql
  • 原文地址:https://www.cnblogs.com/lesroad/p/10051105.html
Copyright © 2011-2022 走看看