go语言实现聊天服务器,可自增自减的协程池

刚来公司实习,每天都在划水,划水狗一只。自己写点东西,大家有意见可以直接留言。


功能:基于go语言和协程池,实现一个简单的聊天服务器。

服务器代码:

/*/////////////////////////////
date:2018-3-17
writer:fengzi
function:用go语言,基于一个可自增的协程池,实现多人聊天
         功能。函数首先创建协程池,然后根据用户连接,创建
         多余的协程加入协程池,如果长时间未使用多余的协程,
         系统自动回收多余协程。
/////////////////////////////*/
import (
    "fmt"
    //    "io"
    "net"
)
 
 
var player map[net.Conn]int = map[net.Conn]int{} //存储用户连接
var message = make(chan net.Conn, 20)            //用户连接的信道
var num int = 0                                  //连接的用户数量
var channelnum int = 0                           //开辟的协程数量
var boolexit int = 0                             //是否需要关闭多余协程
 
 
func main() {
    socket, err := net.Listen("tcp", "localhost:8080")
    if err != nil {
        fmt.Println("net listen error:", err)
        return
    }
    defer socket.Close()
 
 
    for i := 0; i < 2; i++ {
        channelnum++
        go talkChannel()
    }
    for {
        conn, err := socket.Accept()
        if err != nil {
            continue
        }
 
 
        message <- conn
        //扩充协程池
        if num >= 2 {
            fmt.Println("get new channel", num)
            channelnum++
            go talkChannel()
        }
        //如果用户数量长时间小于现在的协程数量,那么关闭多余协程
        if (channelnum >= 2) && (num < channelnum) {
            boolexit++
        } else {
            boolexit = 0
        }
        fmt.Println("boolexit num:", boolexit)
        //连续十次未用到多余协程,关闭多余协程
        if boolexit > 10 {
            message <- nil
            boolexit = 0
        }
        //go talk(conn)
    }
}
func talkChannel() {
    for {
        conn := <-message
        //如果传递的是空,则关闭该协程
        if conn == nil {
            fmt.Println("close channel")
            break
        }
        fmt.Println("channel get one")
        num++
        fmt.Println("talkchannel used:", num)
        defer conn.Close()
        player[conn] = 0
        for {
            buf := make([]byte, 128)
            n, err := conn.Read(buf)
            if err != nil {
                delete(player, conn)
                fmt.Println("one client close:", conn)
                break
            }
            buf = buf[0:n]
            sendall(conn, buf)
        }
        num--
    }
}
func talk(conn net.Conn) {
    defer conn.Close()
    player[conn] = 0
 
 
    for {
        buf := make([]byte, 8192)
        n, err := conn.Read(buf)
        if err != nil {
            delete(player, conn)
            fmt.Println("one client close:", conn)
            break
        }
        buf = buf[0:n]
        fmt.Println(buf)
        sendall(conn, buf)
    }
}
 
 
//广播发送
func sendall(conn net.Conn, buf []byte) {
    for tmp, _ := range player {
        if tmp != conn {
            tmp.Write(buf)
        }
    }
}

客户端:

import (
    "bufio"
    "fmt"
    "net"
    "os"
)
 
 
func main() {
    socket, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        fmt.Println("net.dial error:", err)
        return
    }
    defer socket.Close()
 
 
    go get(socket)
 
 
    for {
        var buff string
        tmp := bufio.NewReader(os.Stdin)
        buff, _ = tmp.ReadString('\n')
        buff = buff[0 : len(buff)-2]
        //fmt.Println(buff)
 
 
        socket.Write([]byte(buff))
    }
}
func get(conn net.Conn) {
    for {
        buf := make([]byte, 1024)
        n, err := conn.Read(buf)
        if err != nil {
            fmt.Println("socket link error:", err)
            break
        }
        buf = buf[0:n]
        fmt.Println("others send:", string(buf))
    }
}
 
 

猜你喜欢

转载自blog.csdn.net/zhanglu_1024/article/details/79596214