版权声明:本文为博主原创文章,未经博主允许不得转载。 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端的控制台输入一些字符,可以看到服务器端返回的转换为大写的字符串。