Golang网络编程实现TCP-CS网络文件传输

网络文件传输:

命令行参数: 在main函数启动时,向整个程序传参。

	语法: go run xxx.go	  argv1 argv2  argv3  argv4

		xxx.go:0 个参数。
		argv1 :第 1 个参数。
		argv2 :第 2个参数。	
		argv3 :第 3 个参数。
		argv4 :第 4 个参数。

	使用: list := os.Args

	          参数3 = list[3]

获取文件属性:

	fileInfo:os.stat(文件访问绝对路径)

	fileInfo 接口,两个接口。

		 Name() 获取文件名。

		 Size() 获取文件大小。
func main()  {
	list := os.Args			// 获取命令行参数

	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())
}

文件传输——发送端(客户端):

1. 提示用户使用命令行参数输入文件名。接收文件名 filepath(含访问路径)

2. 使用 os.Stat()获取文件属性,得到纯文件名 fileName(去除访问路径)

3. 主动发起连接服务器请求,结束时关闭连接。

4. 发送文件名到接收端 conn.Write()

5. 读取接收端回发的确认数据 conn.Read()

6. 判断是否为“ok”。如果是,封装函数 SendFile() 发送文件内容。传参 filePath 和 conn

7. 只读 Open 文件, 结束时Close文件

8. 循环读本地文件,读到 EOF,读取完毕。

9. 将读到的内容原封不动 conn.Write 给接收端(服务器)
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 main()  {
	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)
	}
}

文件传输——接收端(服务器):

1. 创建监听 listener,程序结束时关闭。

2. 阻塞等待客户端连接 conn,程序结束时关闭conn。

3. 读取客户端发送文件名。保存 fileName。

4. 回发“ok”。

5. 封装函数 RecvFile 接收客户端发送的文件内容。传参 fileName 和 conn

6. 按文件名 Create 文件,结束时 Close

7. 循环 Read 发送端网络文件内容,当读到 0 说明文件读取完毕。

8. 将读到的内容原封不动Write到创建的文件中
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 main()  {
	// 创建用于监听的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)
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值