Go语言进阶第07天(UDP请求与文件传输)

1.UDP服务器

package main

import (
	"fmt"
	"net"
	"time"
)

func main00() {
    
    
	// 组织一个 udp 地址结构, 指定服务器的IP+port
	srvAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8006")
	if err != nil {
    
    
		fmt.Println("ResolveUDPAddr err:", err)
		return
	}
	fmt.Println("udp 服务器地址结构,创建完程!!!")
	// 创建用户通信的 socket
	udpConn, err := net.ListenUDP("udp", srvAddr)
	if err != nil {
    
    
		fmt.Println("ListenUDP err:", err)
		return
	}
	defer udpConn.Close()
	fmt.Println("udp 服务器通信socket创建完成!!!")

	// 读取客户端发送的数据
	buf := make([]byte, 4096)

	// 返回3个值,分别是 读取到的字节数, 客户端的地址, error
	n, cltAddr, err := udpConn.ReadFromUDP(buf)
	if err != nil {
    
    
		fmt.Println("ReadFromUDP err:", err)
		return
	}
	// 模拟处理数据
	fmt.Printf("服务器读到 %v 的数据:%s\n", cltAddr, string(buf[:n]))

	// 提取系统当前时间
	daytime := time.Now().String()

	// 回写数据给客户端
	_, err = udpConn.WriteToUDP([]byte(daytime), cltAddr)
	if err != nil {
    
    
		fmt.Println("WriteToUDP err:", err)
		return
	}
}

2.UDP客户端

package main

import (
	"fmt"
	"net"
)

func main01() {
    
    
	// 指定 服务器 IP + port 创建 通信套接字。
	conn, err := net.Dial("udp", "127.0.0.1:8006")
	if err != nil {
    
    
		fmt.Println("net.Dial err:", err)
		return
	}
	defer conn.Close()

	for i := 0; i < 1000000; i++ {
    
    
		// 主动写数据给服务器
		conn.Write([]byte("Are you Ready?"))

		buf := make([]byte, 4096)
		// 接收服务器回发的数据
		n, err := conn.Read(buf)
		if err != nil {
    
    
			fmt.Println("conn.Read err:", err)
			return
		}
		fmt.Println("服务器回发:", string(buf[:n]))
	}

}

3.UDP并发服务器

package main

import (
	"fmt"
	"net"
	"time"
)

func main02() {
    
    

	// 组织一个 udp 地址结构, 指定服务器的IP+port
	srvAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8006")
	if err != nil {
    
    
		fmt.Println("ResolveUDPAddr err:", err)
		return
	}
	fmt.Println("udp 服务器地址结构,创建完程!!!")
	// 创建用户通信的 socket
	udpConn, err := net.ListenUDP("udp", srvAddr)
	if err != nil {
    
    
		fmt.Println("ListenUDP err:", err)
		return
	}
	defer udpConn.Close()
	fmt.Println("udp 服务器通信socket创建完成!!!")

	// 读取客户端发送的数据
	buf := make([]byte, 4096)

	for {
    
    
		// 返回3个值,分别是 读取到的字节数, 客户端的地址, error
		n, cltAddr, err := udpConn.ReadFromUDP(buf) // --- 主go程读取客户端发送数据
		if err != nil {
    
    
			fmt.Println("ReadFromUDP err:", err)
			return
		}
		// 模拟处理数据
		fmt.Printf("服务器读到 %v 的数据:%s\n", cltAddr, string(buf[:n]))

		go func() {
    
     // 每有一个客户端连接上来,启动一个go程 写数据。
			// 提取系统当前时间
			daytime := time.Now().String() + "\n"

			// 回写数据给客户端
			_, err = udpConn.WriteToUDP([]byte(daytime), cltAddr)
			if err != nil {
    
    
				fmt.Println("WriteToUDP err:", err)
				return
			}
		}()
	}
}

4.文件属性

package main

import (
	"fmt"
	"os"
)

func main03() {
    
    
	list := os.Args // 获取命令行参数
	fmt.Println(list)
	if len(list) != 2 {
    
    
		fmt.Println("格式为:go run xxx.go 文件名")
		return
	}
	// 提取文件名
	path := list[1]
	// 获取文件属性
	fileInfo, err := os.Stat(path)
	if err != nil {
    
    
		fmt.Println("os.Stat err:", err)
		return
	}
	fmt.Println("文件名:", fileInfo.Name())
	fmt.Println("文件大小:", fileInfo.Size())
}

5.文件传输-发送

package main

import (
	"fmt"
	"io"
	"net"
	"os"
)

func sendFile(conn net.Conn, filePath string) {
    
    
	// 只读打开文件
	f, err := os.Open(filePath)
	if err != nil {
    
    
		fmt.Println("os.Open err:", err)
		return
	}
	defer f.Close()

	// 从本文件中,读数据,写给网络接收端。 读多少,写多少。原封不动。
	buf := make([]byte, 4096)
	for {
    
    
		n, err := f.Read(buf)
		if err != nil {
    
    
			if err == io.EOF {
    
    
				fmt.Println("发送文件完成。")
			} else {
    
    
				fmt.Println("os.Open err:", err)
			}
			return
		}
		// 写到网络socket中
		_, err = conn.Write(buf[:n])
		if err != nil {
    
    
			fmt.Println("conn.Write err:", err)
			return
		}
	}
}

func main04() {
    
    
	list := os.Args // 获取命令行参数

	if len(list) != 2 {
    
    
		fmt.Println("格式为:go run xxx.go 文件绝对路径")
		return
	}
	// 提取 文件的绝对路径
	filePath := list[1]

	//提取文件名
	fileInfo, err := os.Stat(filePath)
	if err != nil {
    
    
		fmt.Println("os.Stat err:", err)
		return
	}
	fileName := fileInfo.Name()

	// 主动发起连接请求
	conn, err := net.Dial("tcp", "127.0.0.1:8008")
	if err != nil {
    
    
		fmt.Println("net.Dial err:", err)
		return
	}
	defer conn.Close()

	// 发送文件名给 接收端
	_, err = conn.Write([]byte(fileName))
	if err != nil {
    
    
		fmt.Println("conn.Write err:", err)
		return
	}
	// 读取服务器回发的 OK
	buf := make([]byte, 16)
	n, err := conn.Read(buf)
	if err != nil {
    
    
		fmt.Println("conn.Read err:", err)
		return
	}

	if "ok" == string(buf[:n]) {
    
    
		// 写文件内容给服务器——借助conn
		sendFile(conn, filePath)
	}
}

6.文件传输-接收

package main

import (
	"fmt"
	"net"
	"os"
)

func recvFile(conn net.Conn, fileName string) {
    
    
	// 按照文件名创建新文件
	f, err := os.Create(fileName)
	if err != nil {
    
    
		fmt.Println("os.Create err:", err)
		return
	}
	defer f.Close()

	// 从 网络中读数据,写入本地文件
	buf := make([]byte, 4096)
	for {
    
    
		n, _ := conn.Read(buf)
		if n == 0 {
    
    
			fmt.Println("接收文件完成。")
			return
		}
		// 写入本地文件,读多少,写多少。
		f.Write(buf[:n])
	}
}

func main05() {
    
    
	// 创建用于监听的socket
	listener, err := net.Listen("tcp", "127.0.0.1:8008")
	if err != nil {
    
    
		fmt.Println(" net.Listen err:", err)
		return
	}
	defer listener.Close()

	// 阻塞监听
	conn, err := listener.Accept()
	if err != nil {
    
    
		fmt.Println(" listener.Accept() err:", err)
		return
	}
	defer conn.Close()

	// 获取文件名,保存
	buf := make([]byte, 4096)
	n, err := conn.Read(buf)
	if err != nil {
    
    
		fmt.Println(" conn.Read err:", err)
		return
	}
	fileName := string(buf[:n])

	// 回写 ok 给发送端
	conn.Write([]byte("ok"))

	// 获取文件内容
	recvFile(conn, fileName)
}

猜你喜欢

转载自blog.csdn.net/qq_51685718/article/details/127738954
今日推荐