golang使用UDP进行网络通信

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yjp19871013/article/details/82316299

golang提供了网络编程使用net包,使用net包可以进行很基础的socket编程,如果希望了解socket的一些基础知识,可以参看我之前的文章,虽然是Java示例,但是前面的原理说明不会因为语言的差别而不同。今天我们一起看看使用golang如何实现UDP编程。代码分为server端和client两部分,实现的功能与Java版的类似。他们共同使用一份config.go文件。

config.go内容

package config

const (
	SERVER_IP       = "127.0.0.1"
	SERVER_PORT     = 10006
	SERVER_RECV_LEN = 10
)

主要定义了服务器的一些相关常量,包括服务器的IP和端口号,另外还包含服务器一次可以接收的最大字节长度。

server端的代码

package main

import (
	"fmt"
	"net"
	"os"
	"strconv"
	"strings"

	"go-study/socket/config"
)

func main() {
	address := config.SERVER_IP + ":" + strconv.Itoa(config.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 {
		// Here must use make and give the lenth of buffer
		data := make([]byte, config.SERVER_RECV_LEN)
		_, rAddr, err := conn.ReadFromUDP(data)
		if err != nil {
			fmt.Println(err)
			continue
		}

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

		upper := strings.ToUpper(strData)
		_, err = conn.WriteToUDP([]byte(upper), rAddr)
		if err != nil {
			fmt.Println(err)
			continue
		}

		fmt.Println("Send:", upper)
	}
}

代码分为三大块,第一部分使用ResolveUDPAddr函数构造服务端的地址信息,第二部分使用ListenUDP函数,对config,go中指定的端口和地址进行监听,第三部分是一个for循环,该循环不断地从UDP读取客户端数据,然后将其转换为大写字母返回给客户端。ReadFromUDP函数读取UDP数据包,如果没有数据可读,该函数会阻塞。

客户端代码

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strconv"

	"go-study/socket/config"
)

func checkError(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func main() {
	serverAddr := config.SERVER_IP + ":" + strconv.Itoa(config.SERVER_PORT)
	conn, err := net.Dial("udp", serverAddr)
	checkError(err)

	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 > config.SERVER_RECV_LEN {
				toWrite = line[written : written+config.SERVER_RECV_LEN]
			} else {
				toWrite = line[written:]
			}

			n, err = conn.Write([]byte(toWrite))
			checkError(err)

			fmt.Println("Write:", toWrite)

			msg := make([]byte, config.SERVER_RECV_LEN)
			n, err = conn.Read(msg)
			checkError(err)

			fmt.Println("Response:", string(msg))
		}
	}
}

使用Dial函数可以很方便的建立客户端的连接,代码主要部分在for循环,不断地从标准输入读取数据,按照服务器一次接收的数据情况,分批发送数据,然后读取服务器的响应。

在控制台首先运行server端,然后运行client端,在client端的控制台输入一些字符,可以看到服务器端返回的转换为大写的字符串。

猜你喜欢

转载自blog.csdn.net/yjp19871013/article/details/82316299