代码拉取完成,页面将自动刷新
package transport
import (
"errors"
"fmt"
"net"
"sync"
)
type UDPClient struct {
Statistic
host string
port uint16
localport uint16
conn Connection
readChan chan *Packet
writeChan chan *Packet
done chan struct{}
remoteAddr net.Addr
localAddr net.Addr
wait sync.WaitGroup
}
func NewUDPClient(host string, port uint16, locaddr string) (IClient, error) {
laddr, err := net.ResolveUDPAddr("udp", locaddr)
if err != nil {
fmt.Println("客户端地址解析失败: ", err)
return nil, err
}
addrStr := fmt.Sprintf("%s:%d", host, port)
addr, err := net.ResolveUDPAddr("udp", addrStr)
if err != nil {
fmt.Println("服务端地址解析失败: ", err)
return nil, err
}
return &UDPClient{
host: host,
port: port,
localport: uint16(laddr.Port),
readChan: make(chan *Packet, 10),
writeChan: make(chan *Packet, 10),
done: make(chan struct{}),
localAddr: laddr,
remoteAddr: addr,
wait: sync.WaitGroup{},
}, nil
}
func (c *UDPClient) IsReliable() bool {
return false
}
func (c *UDPClient) Name() string {
return fmt.Sprintf("udp client to:%s", fmt.Sprintf("%s:%d", c.host, c.port))
}
func (c *UDPClient) LocalAddr() net.Addr {
return c.localAddr
}
func (c *UDPClient) RemoteAddr() net.Addr {
return c.remoteAddr
}
func (c *UDPClient) StartAndWait() error {
if c.localAddr == nil || c.remoteAddr == nil {
fmt.Println("服务端地址解析失败: ", c.localAddr, c.remoteAddr)
return errors.New("地址解析失败")
}
conn, err := net.DialUDP("udp", c.localAddr.(*net.UDPAddr), c.remoteAddr.(*net.UDPAddr))
if err != nil {
fmt.Println("Can't dial: ", err)
return err
}
udpConnection := newUDPConnection(conn)
c.conn = udpConnection
c.done = make(chan struct{})
fmt.Println("udp client remote addr:", conn.RemoteAddr().String())
fmt.Println("udp client local addr:", conn.LocalAddr().String())
go func() {
defer conn.Close()
for {
select {
case <-c.done:
return
default:
buf := make([]byte, 2048)
n, _, err := conn.ReadFromUDP(buf)
if err != nil {
fmt.Println("failed to read UDP msg because of ", err.Error())
return
}
c.readChan <- &Packet{
Addr: c.remoteAddr,
Data: buf[:n],
}
}
}
}()
return nil
}
func (c *UDPClient) ReadPacketChan() <-chan *Packet {
return c.readChan
}
func (c *UDPClient) WritePacket(packet *Packet) {
c.writeChan <- packet
}
func (c *UDPClient) Close() error {
close(c.done)
return c.conn.Close()
}
// 外部定期调用此接口,实现心跳
func (c *UDPClient) Heartbeat(p *Packet) {
if p == nil {
p = &Packet{
Data: []byte("ping"),
}
}
c.WritePacket(p)
}
func (c *UDPClient) Conn() *Connection {
return &c.conn
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。