golang 實現一個聊天室

最近看了一下go語言,就試着寫了一個聊天室,練練手而已,可是對於我一個搞php的來講,go語言對我啓發很大。php

客服端服務器

package main

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

//定義通道
var ch chan int = make(chan int)

//定義暱稱
var nickname string

func reader(conn *net.TCPConn) {
    buff := make([]byte, 128)
    for {
        j, err := conn.Read(buff)
        if err != nil {
            ch <- 1
            break
        }

        fmt.Println(string(buff[0:j]))
    }
}

func main() {

    tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:9999")
    conn, err := net.DialTCP("tcp", nil, tcpAddr)

    if err != nil {
        fmt.Println("Server is not starting")
        os.Exit(0)
    }

    //爲何不能放到if以前? err不爲nil的話就是painc了 (painc 與 defer 辨析一下!!!)
    defer conn.Close()

    go reader(conn)

    fmt.Println("請輸入暱稱")

    fmt.Scanln(&nickname)

    fmt.Println("你的暱稱爲:", nickname)

    for {
        var msg string
        fmt.Scanln(&msg)
        b := []byte("<" + nickname + ">" + "說:" + msg)
        conn.Write(b)

        //select 爲非阻塞的
        select {
        case <-ch:
            fmt.Println("Server錯誤!請從新鏈接!")
            os.Exit(1)
        default:
            //不加default的話,那麼 <-ch 會阻塞for, 下一個輸入就沒有法進行
        }

    }

服務器端tcp

package main

import (
    "fmt"
    "net"
)

var ConnMap map[string]*net.TCPConn

func checkErr(err error) int {
    if err != nil {
        if err.Error() == "EOF" {
            //用戶退出
            fmt.Println("用戶推出了")
            return 0
        }
        fmt.Println("錯誤")
        return -1
    }
    return 1
}

func say(tcpConn *net.TCPConn) {
    for {
        //讀取一個客戶端發送過來的數據
        data := make([]byte, 128)
        total, err := tcpConn.Read(data)

        fmt.Println(string(data[:total]), err)

        flag := checkErr(err)
        if flag == 0 {
            //退出整個循環
            break
        }

        //廣播形式,向各個客戶端發送數據
        for _, conn := range ConnMap {
            if conn.RemoteAddr().String() == tcpConn.RemoteAddr().String() {
                //不向數據輸入的客戶端發送消息
                continue
            }
            conn.Write(data[:total])
        }
    }
}

func main() {
    tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:9999")
    tcpListener, _ := net.ListenTCP("tcp", tcpAddr)
    /*
        map 定義完後,還要make? (哪些數據類型定義完後,還要make?)
        http://stackoverflow.com/questions/27267900/runtime-error-assignment-to-entry-in-nil-map
    */
    ConnMap = make(map[string]*net.TCPConn)

    for {

        tcpConn, _ := tcpListener.AcceptTCP()
        defer tcpConn.Close()

        ConnMap[tcpConn.RemoteAddr().String()] = tcpConn
        fmt.Println("鏈接的客服端信息:", tcpConn.RemoteAddr().String())

        go say(tcpConn)
    }
}
相關文章
相關標籤/搜索