博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
golang实现udp接入服务器
阅读量:5847 次
发布时间:2019-06-18

本文共 5475 字,大约阅读时间需要 18 分钟。

前端通过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))        }    }}

转载于:https://www.cnblogs.com/ciaos/p/3854867.html

你可能感兴趣的文章
[Erlang 0004] Centos 源代码编译 安装 Erlang
查看>>
51 Nod 1027 大数乘法【Java大数乱搞】
查看>>
三维重建技术概述
查看>>
AI x 量化:华尔街老司机解密智能投资正确姿势
查看>>
IT史上十大收购案
查看>>
数据切分——Atlas介绍
查看>>
游戏引擎cocos2d-android使用大全
查看>>
oracle job 定时执行参数
查看>>
Android命令Monkey压力测试,详解
查看>>
负载均衡(LB)集群 dr
查看>>
(转)直接拿来用!最火的iOS开源项目(一)
查看>>
div+css+js 树形菜单
查看>>
android EventBus 3.0 混淆配置
查看>>
我的友情链接
查看>>
DNS区域委派与转发
查看>>
Windows Server 2008 RemoteApp---发布应用程序
查看>>
白帽子技术分析会话劫持实战讲解
查看>>
我的友情链接
查看>>
yum的三种方式
查看>>
人生苦短我用python(02)动态加载模块
查看>>