Golang UDP通信案例


Go UDP服務端代碼

package main

import (
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"net"
)

type DataPacket struct {
	Type string
	Body string
}

func main() {
	//綁定端口
	tcpAddr, err := net.ResolveTCPAddr("tcp", ":19010")
	if err != nil {
		fmt.Println(err.Error())
	}
	//監聽
	listener, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		fmt.Println(err.Error())
	}
	defer listener.Close()
	//開始接收數據
	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println(err.Error())
		}
		go Handler(conn)
	}

}

func Handler(conn net.Conn) {
	defer conn.Close()
	//每次讀取數據長度
	buf := make([]byte, 256)
	_, err := conn.Read(buf)
	if err != nil {
		return
	}
	result, Body := check(buf)
	if result {
		fmt.Printf("接收到報文內容:{%s}\n", hex.EncodeToString(Body))
	}

}

func check(buf []byte) (bool, []byte) {
	Length := DataLength(buf)
	if Length < 3 || Length > 256 {
		return false, nil
	}
	Body := buf[:Length]
	return uint16(len(Body))-2 != Length, Body
}

func DataLength(buf []byte) uint16 {
	return binary.BigEndian.Uint16(inversion(buf[:2])) + 2
}

//反轉字節
func inversion(buf []byte) []byte {
	for i := 0; i < len(buf)/2; i++ {
		temp := buf[i]
		buf[i] = buf[len(buf)-1-i]
		buf[len(buf)-1-i] = temp
	}
	return buf
}


Go UDP客戶端段代碼


package main

import (
	"bufio"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"net"
	"os"
	"strings"
	"time"
)

func main() {

	//請求地址
	conn, err := net.Dial("udp", "127.0.0.1:30001")
	if err != nil {
		fmt.Println("net.Dial err:", err)
		return
	}
	//假設該設備序號
	SerialNumbe := "AA001D80"
	defer conn.Close()
	//這里是設備正常請求
	go func() {
		for {
			//報文長度占用倆個字節(報文長度不包含自身),類型1個字節,設備序列號4個字節
			decodeString, err := hex.DecodeString("050000" + SerialNumbe)
			if err != nil {
				fmt.Println("錯誤的16進制字符串!")
			}
			fmt.Printf("發送的心跳包:{%s}\n", ByteToHex(decodeString))
			conn.Write(decodeString)
			//心跳發送后,睡眠5秒
			time.Sleep(time.Duration(10) * time.Second)
		}
	}()
	//這里是其他操作
	go func() {
		input := bufio.NewScanner(os.Stdin)
		for input.Scan() {
			line := input.Text()
			fmt.Println(line)
			bytes, err := hex.DecodeString(line)
			if err != nil {
				//格式:
				//	報文長度,倆個字節(報文長度不包含自身)
				//	報文類型,一個字節
				// 	報文內容,自定義
				//例如:
				//	0300090023
				fmt.Println("請輸入正確的16進制字符串!")
			} else {

				conn.Write(bytes)
			}
		}

	}()
	buf := make([]byte, 256)
	for {
		_, err := conn.Read(buf)
		if err != nil {
			fmt.Println("conn.Read err:", err)
			return
		}
		fmt.Printf("收到服務器心跳包返回:{%s}\n", ByteToHex(buf[:DataLength(buf)]))
		fmt.Print("請輸入請求報文:\n")

	}

}

//字節轉16進制字符串,並且字符轉大寫
func ByteToHex(buf []byte) string {
	return strings.ToUpper(hex.EncodeToString(buf))
}

func DataLength(buf []byte) uint16 {
	return binary.BigEndian.Uint16(inversion(buf[:2]))
}

//反轉字節
func inversion(buf []byte) []byte {
	for i := 0; i < len(buf)/2; i++ {
		temp := buf[i]
		buf[i] = buf[len(buf)-1-i]
		buf[len(buf)-1-i] = temp
	}
	return buf
}


效果如下:

  • 正常心跳
  • 其他請求:
    這里在客戶端輸入報文010002

    服務端收到后顯示:

代碼地址: https://gitee.com/nooft/udp_tcp_demo.git


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM