分享
  1. 首页
  2. 文章

golang实现udp接入服务器

ciaos · · 13466 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前端通过udp与接入服务器连接,接入服务器与后端tcp服务器维持tcp连接。目录结构及后端tcp服务器代码同上一篇博客。

main.go

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

udplotus.go

package udplotus
import (
 "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]*Request
type 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 main
import (
 "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))
 }
 }
}

有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:ciaos

查看原文:golang实现udp接入服务器

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
13466 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏