GO UDP编程

2022-01-14  本文已影响0人  舍是境界

本文介绍golang下的UDP编程,并给到相关示例代码:

用户数据报协议(User Datagram Protocol,缩写为UDP),又称用户数据报文协议,是一个简单的面向数据报(package-oriented)的传输层协议,正式规范为RFC 768。

UDP只提供数据的不可靠传递,它一旦把应用程序发给网络层的数据发送出去,就不保留数据备份(所以UDP有时候也被认为是不可靠的数据报协议)。

UDP在IP数据报的头部仅仅加入了复用和数据校验。

由于缺乏可靠性且属于非连接导向协议,UDP应用一般必须允许一定量的丢包、出错和复制粘贴。

注意事项

  1. 在接收udp包时,如果接收包时给定的buffer太小的话,就要自己解决粘包问题。
  2. udp包的发送和接收不保证一定成功,不保证按正确顺序抵达。
  3. 简单实现方式可以改为一次接收保证数据完全得到,超限的忽略

示例代码:

package net

import (
    "bufio"
    "bytes"
    "fmt"
    "net"
    "os"
    "strconv"
    "strings"
)

const (
    SERVER_IP           = "127.0.0.1"
    SERVER_PORT         = 10006
    SERVER_RECV_MAX_LEN = 2048 //2k
)

func StartUdpServer() {
    address := SERVER_IP + ":" + strconv.Itoa(SERVER_PORT)
    addr, err := net.ResolveUDPAddr("udp", address)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    conn, err := net.ListenUDP("udp", addr)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    defer conn.Close()

    for {
        data := make([]byte, SERVER_RECV_MAX_LEN)
        _, rAddr, err := conn.ReadFromUDP(data)
        if err != nil {
            fmt.Println(err)
            continue
        }
        data = bytes.Trim(data, "\x00")

        strData := string(data)
        fmt.Println("Received", strData)

        sendData := "received:" + strData
        _, err = conn.WriteToUDP([]byte(sendData), rAddr)
        if err != nil {
            fmt.Println(err)
            continue
        }

        fmt.Println("Received", sendData)
    }
}

func StartUdpClient(){
    serverAddr := SERVER_IP + ":" + strconv.Itoa(SERVER_PORT)
    conn, err := net.Dial("udp", serverAddr)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    defer conn.Close()

    input := bufio.NewScanner(os.Stdin)
    for input.Scan() {
        line := input.Text()
        lineLen := len(line)

        n := 0
        for written := 0; written < lineLen; written += n {
            var toWrite string
            if lineLen - written > SERVER_RECV_MAX_LEN {
                toWrite = line[written: written +SERVER_RECV_MAX_LEN]
            }else {
                toWrite = line[written:]
            }

            n, err = conn.Write([]byte(toWrite))
            if err != nil {
                fmt.Println(err)
                os.Exit(1)
            }

            fmt.Println("client Write: " + toWrite)

            msg := make([]byte, SERVER_RECV_MAX_LEN)
            n, err = conn.Read(msg)
            if err != nil {
                fmt.Println(err)
                os.Exit(1)
            }

            msg = bytes.Trim(msg, "\x00")

            fmt.Println("client received: " + strings.TrimSpace(string(msg)))

        }
    }
}

输出结果:

#客户端:
11
client Write: 11
client received: received:11
shimahahahhahaha
client Write: shimahahahhahaha
client received: received:shimahahahhahaha

#服务端
Received 11
Received received:11
Received shimahahahhahaha
Received received:shimahahahhahaha

小结

本文通过代码简单使用了golang的udp编程,希望对你能有所帮助

上一篇 下一篇

猜你喜欢

热点阅读