Go网络编程-网络文件传输

具体流程

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

	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 给接收端(服务器)

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

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

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

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

	4. 回发“ok”。

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

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

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

	8. 将读到的内容原封不动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 {
		//将文件读入buf中
		n, err := f.Read(buf)
		if err != nil {
			//如果读到末尾位置,即为完成
			if err == io.EOF {
				fmt.Println("发送文件完成。")
			} else {
				fmt.Println("os.Open err:", err)
			}
			return
		}
		// 将buf写到网络socket中,传给服务器端
		_, err = conn.Write(buf[:n])
		if err != nil {
			fmt.Println("conn.Write err:", err)
			return
		}
	}
}

func main()  {
	//从命令行中读取参数  在命令行中的格式应为go run xxx.go C:\a.txt(文件路径)
	//返回值为string切片
	list := os.Args
	if len(list) != 2 {
		fmt.Println("格式为错误")
		return
	}
	// 提取文件的绝对路径(文件路径在切片index为1中存储)
	filePath := list[1]

	//使用os.Stat函数,传入文件路径,返回文件属性信息
	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
	}
	//当我们发送文件名给服务器后,服务器回返回ok返回
	if "ok" == string(buf[:n]) {
		// 写文件内容给服务器——借助conn
		sendFile(conn, filePath)
	}

}

文件接受端

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  {
		//不断向buf中写入,从客户端传回的内容
		n,_:=conn.Read(buf)
		if n==0 {
			fmt.Println("文件接受完成")
			return
		}
		//向文件中写入buf的内容
		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("conn 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)
}

演示结果

 在命令行中单起客户端,并且传入文件路径,即可传输文件,音频等等…
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值