golang實現udp接入伺服器

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

前端通過udp與接入伺服器串連,接入伺服器與後端tcp伺服器維持tcp串連。目錄結構及後端tcp伺服器代碼同上一篇部落格。

main.go

package mainimport (    "lotuslib")const (    ip   = "0.0.0.0"    port = 1987)func main() {    udplotus.UdpLotusMain(ip, port)}

udplotus.go

package udplotusimport (    "encoding/json"    "log"    "net"    "strconv"    "time")const (    proxy_timeout = 5    proxy_server  = "127.0.0.1:1988"    msg_length    = 1024)type Request struct {    reqId      int    reqContent string    rspChan    chan<- string // writeonly chan}var requestMap map[int]*Requesttype Clienter struct {    client  net.Conn    isAlive bool    SendStr chan *Request    RecvStr chan string}func (c *Clienter) Connect() bool {    if c.isAlive {        return true    } else {        var err error        c.client, err = net.Dial("tcp", proxy_server)        if err != nil {            return false        }        c.isAlive = true        log.Println("connect to " + proxy_server)    }    return true}func ProxySendLoop(c *Clienter) {    //store reqId and reqContent    senddata := make(map[string]string)    for {        if !c.isAlive {            time.Sleep(1 * time.Second)            c.Connect()        }        if c.isAlive {            req := <-c.SendStr            //construct request json string            senddata["reqId"] = strconv.Itoa(req.reqId)            senddata["reqContent"] = req.reqContent            sendjson, err := json.Marshal(senddata)            if err != nil {                continue            }            _, err = c.client.Write([]byte(sendjson))            if err != nil {                c.RecvStr <- string("proxy server close...")                c.client.Close()                c.isAlive = false                log.Println("disconnect from " + proxy_server)                continue            }            //log.Println("Write to proxy server: " + string(sendjson))        }    }}func ProxyRecvLoop(c *Clienter) {    buf := make([]byte, msg_length)    recvdata := make(map[string]string, 2)    for {        if !c.isAlive {            time.Sleep(1 * time.Second)            c.Connect()        }        if c.isAlive {            n, err := c.client.Read(buf)            if err != nil {                c.client.Close()                c.isAlive = false                log.Println("disconnect from " + proxy_server)                continue            }            //log.Println("Read from proxy server: " + string(buf[0:n]))            if err := json.Unmarshal(buf[0:n], &recvdata); err == nil {                reqidstr := recvdata["reqId"]                if reqid, err := strconv.Atoi(reqidstr); err == nil {                    req, ok := requestMap[reqid]                    if !ok {                        continue                    }                    req.rspChan <- recvdata["resContent"]                }                continue            }        }    }}func handle(conn *net.UDPConn, remote *net.UDPAddr, id int, tc *Clienter, data []byte) {    handleProxy := make(chan string)    request := &Request{reqId: id, rspChan: handleProxy}    request.reqContent = string(data)    requestMap[id] = request    //send to proxy    select {    case tc.SendStr <- request:    case <-time.After(proxy_timeout * time.Second):        conn.WriteToUDP([]byte("proxy server send timeout."), remote)    }    //read from proxy    select {    case rspContent := <-handleProxy:        conn.WriteToUDP([]byte(rspContent), remote)    case <-time.After(proxy_timeout * time.Second):        conn.WriteToUDP([]byte("proxy server recv timeout."), remote)    }}func UdpLotusMain(ip string, port int) {    //start tcp server    addr, err := net.ResolveUDPAddr("udp", ip+":"+strconv.Itoa(port))    if err != nil {        log.Fatalln("net.ResolveUDPAddr fail.", err)        return    }    conn, err := net.ListenUDP("udp", addr)    if err != nil {        log.Fatalln("net.ListenUDP fail.", err)        //os.Exit(1)        return    }    log.Println("start udp server " + ip + " " + strconv.Itoa(port))    defer conn.Close()    //start proxy connect and loop    var tc Clienter    tc.SendStr = make(chan *Request, 1000)    tc.RecvStr = make(chan string)    tc.Connect()    go ProxySendLoop(&tc)    go ProxyRecvLoop(&tc)    //listen new request    requestMap = make(map[int]*Request)    buf := make([]byte, msg_length)    var id int = 0    for {        rlen, remote, err := conn.ReadFromUDP(buf)        if err == nil {            id++            log.Println("connected from " + remote.String())            go handle(conn, remote, id, &tc, buf[:rlen]) //new thread        }    }}

udpclient.go

package mainimport (    "bufio"    "fmt"    "net"    "os")func main() {    addr, err := net.ResolveUDPAddr("udp", ":1987")    if err != nil {        fmt.Println("net.ResolveUDPAddr fail.", err)        os.Exit(1)    }    socket, err := net.DialUDP("udp", nil, addr)    if err != nil {        fmt.Println("net.DialUDP fail.", err)        os.Exit(1)    }    defer socket.Close()    r := bufio.NewReader(os.Stdin)    for {        switch line, ok := r.ReadString('\n'); true {        case ok != nil:            fmt.Printf("bye bye!\n")            return        default:            socket.Write([]byte(line))            data := make([]byte, 1024)            _, remoteAddr, err := socket.ReadFromUDP(data)            if err != nil {                fmt.Println("error recv data")                return            }            fmt.Printf("from %s:%s\n", remoteAddr.String(), string(data))        }    }}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.