简单的命令行TCP聊天服务器

 提示:转载请注明原文链接

 本文永久链接:http://360us.net/article/38.html

服务器端:

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "net"
    "os"
    "strconv"
    "time"
)

var User map[string]*net.TCPConn

func main() {
    var tcpAddr *net.TCPAddr
    var tcpListen *net.TCPListener
    var tcpConn *net.TCPConn
    var err error
    User = make(map[string]*net.TCPConn)

    //监听端口
    tcpAddr, err = net.ResolveTCPAddr("tcp4", ":5000")
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    //监听
    tcpListen, err = net.ListenTCP("tcp4", tcpAddr)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    fmt.Println("监听在5000端口")

    //接受连接
    for {
        tcpConn, err = tcpListen.AcceptTCP()
        if err != nil {
            fmt.Println(err)
            os.Exit(1)
        }
        Addr := tcpConn.RemoteAddr()
        name := strconv.FormatInt(time.Now().UnixNano(), 16)
        User[name] = tcpConn
        fmt.Println("接受来自", Addr.String(), "的连接,分配用户名", name)
        go handler(name, tcpConn)

        time.Sleep(time.Second)
    }
}

//处理连接
func handler(name string, conn *net.TCPConn) {
    sayHello(name, conn)
    buffer := bufio.NewReader(conn)
    for {
        str, err := buffer.ReadString('\n')
        if err != nil {
            break
        }

        fmt.Println("收到", name, "的信息:", str)
        sayAll(name, str)
    }

    closeClient(name)
}

//用户断开
func closeClient(name string) {
    fmt.Println("用户", name, "已断开连接")
    delete(User, name)
    userCount := len(User)
    var msg = new(bytes.Buffer)
    _, err := fmt.Fprintf(msg, "用户%s已断开连接,总人数%d\n", name, userCount)
    if err == nil {
        sayAll(name, msg.String())
    }
}

//用户连接时,发送欢迎消息
func sayHello(name string, conn *net.TCPConn) bool {
    var msg = new(bytes.Buffer)
    _, err := fmt.Fprintf(msg, "%s,欢迎你!当前总人数:%d\n", name, len(User))
    if err != nil {
        return false
    }
    _, err = conn.Write([]byte(msg.String()))
    if err != nil {
        return false
    }

    return true
}

//广播消息
func sayAll(name, msg string) {
    for k, c := range User {
        //当前用户不广播
        if k == name {
            continue
        }
        _, err := c.Write([]byte(name + "说:" + msg))
        if err != nil {
            continue
        }
    }
}

客户端:

package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
)

func main() {
    var tcpConn *net.TCPConn
    var err error
    var str string

    raddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:5000")
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    tcpConn, err = net.DialTCP("tcp4", nil, raddr)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    fmt.Println("连接服务器成功")
    go send(tcpConn)

    //tcpConn.SetDeadline(time.Now().Add(time.Second * 3))
    buffer := bufio.NewReader(tcpConn)

    //读服务器响应
    for {
        str, err = buffer.ReadString('\n')
        if err != nil {
            fmt.Println(err.Error())
            break
        }
        fmt.Println(str)
    }
    fmt.Println("连接已断开")
    os.Exit(0)
}

//获取输入,发送消息
func send(conn *net.TCPConn) {
    var err error
    var input string
    var reader = bufio.NewReader(os.Stdin)

    for {
        input, err = reader.ReadString('\n')
        if err != nil {
            fmt.Println("获取输入错误", err)
            break
        }

        _, err = conn.Write([]byte(input))
        if err != nil {
            fmt.Println(err)
            break
        }
    }
}


 评论
昵称
邮箱
网址
最多500个字符