go聊天代碼

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

main.go(server)


package main


import (
    "git.letv.cn/uts/qpid-go_0_10/libqpid"
    "./tbs"
    // "fmt"
    "time"
)

func main() {
    var cb tbs.EventCallback = onTest
    //擷取指派器單例
    tbs.SetCallBack(&cb)
    service := ":1200"
    tbs.ServerStarted(service)

    //因為主線程不會等子線程而直接關閉進程,這樣會看不到效果,所以我在這裡加了阻塞式延時
    time.Sleep(time.Second * 1)
}

//回調出得到的就是一個event對象了
func onTest(event *tbs.Event) {
    // fmt.Println("onTest", event.Params["id"])
}


tbs.go

package tbs

import (
    "fmt"
    "net"
    "os"
    // "time"
)

type Dispatcher struct {
    listeners map[string]*EventChain
}

type EventChain struct {
    chs       []chan *Event
    callbacks []*EventCallback
}

func CreateEventChain() *EventChain {
    return &EventChain{chs: []chan *Event{}, callbacks: []*EventCallback{}}
}

type Event struct {
    eventName string
    Params    map[string]interface{}
}

func ServerStarted(port string) {
    fmt.Println("server started.")
    tcpAddr, err := net.ResolveTCPAddr("tcp4", port)
    checkError(err)
    listener, err := net.ListenTCP("tcp", tcpAddr)
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        go handleClient(conn)
    }
}

func handleClient(conn net.Conn) {
    // conn.SetReadDeadline(time.Now().Add(2 * time.Minute)) // set 2 minutes timeout
    request := make([]byte, 128) // set maxium request length to 128B to prevent flood attack
    defer conn.Close()           // close connection before exit
    for {
        read_len, err := conn.Read(request)

        if err != nil {
            // fmt.Println(err)
            if read_len == 0 {
                //移除監聽
                dispatcher := SharedDispatcher()
                dispatcher.RemoveEventListener("test", _cb)
            }
            break
        }
        fmt.Println("message: ")
        fmt.Println(string(request))
        if read_len == 0 {
            //移除監聽
            dispatcher := SharedDispatcher()
            dispatcher.RemoveEventListener("test", _cb)
            break // connection already closed by client
        } else {
            onData(request)
        }

        request = make([]byte, 128) // clear last read content
    }
}

func onData(request []byte) {
    //隨便弄個事件攜帶的參數,我把參數定義為一個map
    params := make(map[string]interface{})
    params["id"] = 1000

    //建立一個事件對象
    event := CreateEvent("test", params)
    event.Params["bytes"] = request

    //擷取指派器單例
    dispatcher := SharedDispatcher()

    //添加監聽
    dispatcher.AddEventListener("test", _cb)

    //把事件指派出去
    dispatcher.DispatchEvent(event)
}

func checkError(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
        // os.Exit(1)
    }
}

func CreateEvent(eventName string, params map[string]interface{}) *Event {
    return &Event{eventName: eventName, Params: params}
}

type EventCallback func(*Event)
var _instance *Dispatcher
var _cb *EventCallback

func SetCallBack(callback *EventCallback) {
    _cb = callback
}

func SharedDispatcher() *Dispatcher {
    if _instance == nil {
        _instance = &Dispatcher{}
        _instance.Init()
    }

    return _instance
}

func (this *Dispatcher) Init() {
    this.listeners = make(map[string]*EventChain)
}

func (this *Dispatcher) AddEventListener(eventName string, callback *EventCallback) {
    eventChain, ok := this.listeners[eventName]
    if !ok {
        eventChain = CreateEventChain()
        this.listeners[eventName] = eventChain
    }

    exist := false
    for _, item := range eventChain.callbacks {
        if item == callback {
            exist = true
            break
        }
    }

    if exist {
        return
    }

    ch := make(chan *Event)

    fmt.Printf("add listener: %s\n", eventName)
    eventChain.chs = append(eventChain.chs[:], ch)
    eventChain.callbacks = append(eventChain.callbacks[:], callback)

    go func() {
        for {
            event := <-ch
            if event == nil {
                break
            }
            (*callback)(event)
        }
    }()
}

func (this *Dispatcher) RemoveEventListener(eventName string, callback *EventCallback) {
    eventChain, ok := this.listeners[eventName]
    if !ok {
        return
    }

    var ch chan *Event
    exist := false
    key := 0
    for k, item := range eventChain.callbacks {
        if item == callback {
            exist = true
            ch = eventChain.chs[k]
            key = k
            break
        }
    }

    if exist {
        fmt.Printf("remove listener: %s\n", eventName)
        ch <- nil

        eventChain.chs = append(eventChain.chs[:key], eventChain.chs[key+1:]...)
        eventChain.callbacks = append(eventChain.callbacks[:key], eventChain.callbacks[key+1:]...)
    }
}

func (this *Dispatcher) DispatchEvent(event *Event) {
    eventChain, ok := this.listeners[event.eventName]
    if ok {
        // fmt.Printf("dispatch event: %s\n", event.eventName)
        for _, chEvent := range eventChain.chs {
            chEvent <- event
        }
    }
}


main.go(client)

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "os"
    "strings"
)
   
//串連伺服器
func connectServer() {
    //接通
    conn, err := net.Dial("tcp", "10.75.144.119:1200")
    checkError(err)
    fmt.Println("串連成功!\n")
    //輸入
    inputReader := bufio.NewReader(os.Stdin)
    fmt.Println("你是誰?")
    name, _ := inputReader.ReadString('\n')
    //
    trimName := strings.Trim(name, "\r\n")
    conn.Write([]byte(trimName + " 接入了\n "))
    for {
        fmt.Println("我們來聊天吧!按quit退出")
        //讀一行
        input, _ := inputReader.ReadString('\n')
        trimInput := strings.Trim(input, "\r\n")
        //如果quit就退出
        if trimInput == "quit" {
            fmt.Println("再見")
            conn.Write([]byte(trimName + " 退出了 "))
            return
        }
        //寫出來
        _, err = conn.Write([]byte(trimName + " says " + trimInput))
    }
}

//檢查錯誤
func checkError(err error) {
    if err != nil {
        log.Fatal("an error!", err.Error())
    }
}

//主函數
func main() {
    //串連servser
    connectServer()
}




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.