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

本文介绍了借助TCP完成网络文件传输(客户端上传本地文件到服务器)的基本思路,包括客户端发送文件名、服务器确认、客户端发送文件数据、服务器写入文件等步骤,还给出了获取文件名的示例代码及一个网络文件传输的例子。

网络文件传输(客户端上传本地文件到服务器)

借助TCP完成文件的传输,基本思路如下:

         1.客户端向服务器发送文件名,服务器保存该文件名。

         2.服务端向客户端返回去一个消息ok,确认文件名保存成功。

         3.客户端收到消息后,开始向服务器发送文件数据。

         4.服务端读取文件内容,写入到之前保存好的文件中。

  示意图大致如下:

首先获取文件名,借助os包中的stat()函数来获取文件属性信息。在函数返回的文件属性中包含文件名和文件大小。Stat函数传入参数name是文件访问的绝对路径。

   func Stat (name string) (FileInfo , error) 

   type FileInfo interface{

       Name() string   //文件名字

       Size() int64      //文件大小

       IsDir() bool      //是否是一个目录

        ........

   }

实现一个网络文件传输的例子:

发送方:

package main

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

func main()  {

	//1.获取命令行参数
	list := os.Args
	if len(list) != 2{
		fmt.Println("需要两个参数")
		return
	}

	//2.提取文件的绝对路径  exp :/home/sxf/hh
	filePath := list[1]

	//3.提取不包含路径的文件名 exp:hh
	fileInfo ,err := os.Stat(filePath)//fileInfo中包含文件名和文件大小
	if err != nil{
		fmt.Println("os.Stat err",err)
		return
	}
	fileName :=fileInfo.Name() //文件名hh
	fileSize :=fileInfo.Size() //文件大小
	fmt.Println("文件名:",fileName)
	fmt.Println("文件大小",fileSize)

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

	//5.发送文件名给接收端
	conn.Write([]byte(fileName))

	//6.读取接收端回发的响应数据(ok)
	buf := make([]byte,4096)
	n, err := conn.Read(buf)
	if err != nil{
		fmt.Println("conn.Read err",err)
		return
	}

	//7.判断这个数据是否是ok
	if "ok" == string(buf[:n]){
		//8.是ok,写文件内容给接收端--借助conn
		sendcontent(conn,filePath)
	}


}

//发送文件内容给接受端
func sendcontent(conn net.Conn,filePath string)  {

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

	//8.2从本地文件读数据,写给接收端
	buf := make([]byte,4096)
	for  {
		n,err :=f.Read(buf)  //读取本地文件放入缓冲区buf中
		if err != nil{
			if err == io.EOF {
				fmt.Println("读取文件完成")
			}else {
				fmt.Println("f.Read err",err)
			}
			return
		}
		_,err =conn.Write(buf[:n])//将缓冲区buf中数据写到网络socket中
		if err != nil{
			fmt.Println("conn.Write err",err)
			return
		}
	}

}

接收方: 

package main

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

func main()  {
	//1.指定服务器通信协议、IP地址、Port端口,创建一个用于监听的socket---listener
	listener ,err := net.Listen("tcp","127.0.0.1:8008")
	if err != nil{
		fmt.Println("net.Listener err:",err)
		return
	}
	defer listener.Close()//关闭socket


	//2.阻塞监听客户端连接请求,成功建立连接,返回用于通信的socket---conn
	conn ,err := listener.Accept()
	if err != nil{
		fmt.Println("listener.Accept err:",err)
		return
	}
	defer conn.Close()//关闭socket

	//3.从conn套接字中获取文件名,写入缓存buf中
	buf := make([]byte,4096)
	n ,err := conn.Read(buf)
	if err != nil{
		fmt.Println("conn.Read err:",err)
		return
	}

	//4.从buf中提取文件名
	fileName := string(buf[:n])

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

	//6.获取文件内容
	recivefile(conn,fileName)
}

func recivefile(conn net.Conn,fileName string)  {

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

	//6.2从网络socket中读数据,写入本地文件中
	buf := make([]byte,4096)
	
	for  {

		n,_ := conn.Read(buf) //从conn中读数据到buf中
		if n == 0{  //判断是否读取数据完毕
			fmt.Println("接收文件完毕")
			return
		}

		//将buf中的数据写入到本地文件
		f.Write(buf[:n])
	}

}

发送方发送本地的一个文件给接收方:

接收方收到文件,接收到的文件在GOPATH/src目录下

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值