Go语言 之TCP文件传输
服务端实现流程大致如下:
- 创建监听listener,程序结束时关闭。
- 阻塞等待客户端连接,程序结束时关闭conn。
- 读取客户端发送文件名。保存fileName。
- 回发“ok”给客户端做应答
- 封装函数 RecvFile接收客户端发送的文件内容。传参fileName 和conn
- 按文件名Create文件,结束时Close
- 循环Read客户端发送的文件内容,当读到EOF说明文件读取完毕。
- 将读到的内容原封不动Write到创建的文件中
package main import (
"fmt"
"net"
"os"
"runtime"
) func Handler(conn net.Conn) {
buf := make([]byte, 2048)
//读取客户端发送的内容
n, err := conn.Read(buf)
if err != nil {
fmt.Println(err)
return
}
fileName := string(buf[:n])
//获取客户端ip+port
addr := conn.RemoteAddr().String()
fmt.Println(addr + ": 客户端传输的文件名为--" + fileName)
//告诉客户端已经接收到文件名
conn.Write([]byte("ok"))
//创建文件
f, err := os.Create(fileName)
if err != nil {
fmt.Println(err)
return
}
//循环接收客户端传递的文件内容
for {
buf := make([]byte, 2048)
n, _ := conn.Read(buf)
//结束协程
if string(buf[:n]) == "finish" {
fmt.Println(addr + ": 协程结束")
runtime.Goexit()
}
f.Write(buf[:n])
}
defer conn.Close()
defer f.Close()
} func main() {
//创建tcp监听
listen, err := net.Listen("tcp", ":8000")
if err != nil {
fmt.Println(err)
return
}
defer listen.Close() for {
//阻塞等待客户端
conn, err := listen.Accept()
if err != nil {
fmt.Println(err)
return
}
//创建协程
go Handler(conn)
}
}
客户端实现流程大致如下:
- 提示用户输入文件名。接收文件名path(含访问路径)
- 使用os.Stat()获取文件属性,得到纯文件名(去除访问路径)
- 主动连接服务器,结束时关闭连接
- 给接收端(服务器)发送文件名conn.Write()
- 读取接收端回发的确认数据conn.Read()
- 判断是否为“ok”。如果是,封装函数SendFile() 发送文件内容。传参path和conn
- 只读Open文件, 结束时Close文件
- 循环读文件,读到EOF终止文件读取
- 将读到的内容原封不动Write给接收端(服务器)
package main import (
"fmt"
"io"
"net"
"os"
) //发送文件到服务端
func SendFile(filePath string, fileSize int64, conn net.Conn) {
f, err := os.Open(filePath)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
var count int64
for {
buf := make([]byte, 2048)
//读取文件内容
n, err := f.Read(buf)
if err != nil && io.EOF == err {
fmt.Println("文件传输完成")
//告诉服务端结束文件接收
conn.Write([]byte("finish"))
return
}
//发送给服务端
conn.Write(buf[:n]) count += int64(n)
sendPercent := float64(count) / float64(fileSize) * 100
value := fmt.Sprintf("%.2f", sendPercent)
//打印上传进度
fmt.Println("文件上传:" + value + "%")
}
} func main() {
fmt.Print("请输入文件的完整路径:")
//创建切片,用于存储输入的路径
var str string
fmt.Scan(&str)
//获取文件信息
fileInfo, err := os.Stat(str)
if err != nil {
fmt.Println(err)
return
}
//创建客户端连接
conn, err := net.Dial("tcp", ":8000")
if err != nil {
fmt.Println(err)
return
}
defer conn.Close()
//文件名称
fileName := fileInfo.Name()
//文件大小
fileSize := fileInfo.Size()
//发送文件名称到服务端
conn.Write([]byte(fileName))
buf := make([]byte, 2048)
//读取服务端内容
n, err := conn.Read(buf)
if err != nil {
fmt.Println(err)
return
}
revData := string(buf[:n])
if revData == "ok" {
//发送文件数据
SendFile(str, fileSize, conn)
}
}
Go语言 之TCP文件传输的更多相关文章
- 艺萌TCP文件传输及自动更新系统介绍(TCP文件传输)(四)
艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开源,作者是英国的,开发时间5年多,框架很稳定. 项 ...
- 艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输)(一)
艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开元,作者是英国的,开发时间5年多,框架很稳定. 项 ...
- qt+boost::asio+tcp文件传输
客户端: void qt_boost::pbSendFileClicked(){ QString filename = ui.leFileName->text(); QByteArray ba ...
- Java 简单TCP文件传输
服务端 package TCP; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputSt ...
- python基础实现tcp文件传输
准备工作,实现文件上传需要那些工具呢? socket(传输).open()(打开文件).os(读取文件信息),当然还有辅助类sys和json,下面我们开始吧 import socket,sys imp ...
- Java Tcp文件传输---转载
/** 客户端 1.服务端点 2.读取客户端已有的文件数据 3.通过socket输出流发给服务端 4.读取服务端反馈信息 5.关闭 **/ import java.io.*; import java. ...
- 在TCP文件传输中如何判断java流的末尾
感谢前辈们的解答:https://bbs.csdn.net/topics/280085530 问题描述: 服务端向客户端发送数据流,服务端发完了数据不关闭流. 我在客户端读流,我无法读到-1,所以无法 ...
- Linux网络编程:socket文件传输范例
基于TCP流协议的socket网络文件传输Demo: 实现:C语言功能:文件传输(可以传任何格式的文件) /********************************************** ...
- Windows网络编程:winsock文件传输范例
基于TCP流协议的winsock网络文件传输Demo: 实现:C语言 功能:文件传输(可以传任何格式的文件) /******************************************** ...
随机推荐
- asp.net类似于js中的setTimeOut()的函数作用?
asp.net类似于js中的setTimeOut()的函数作用? 插入这行即可,定时2秒,再运行下一步: System.Threading.Thread.Sleep(); 加个随机数 Random r ...
- D盘Program Files 文件夹里文件不显示,没隐藏。怎么才能显示出来?
D盘里有两个一模一样的Program Files 文件夹,文件夹里文件不显示,没隐藏.怎么才能显示出来?新买不久的电脑,win8.1系统 点击开始---运行---输入“cmd”(没有引号)---在弹出 ...
- 解析Illumina+PacBio组装策略
解析Illumina+PacBio组装策略 (2016-12-08 13:21:58) 转载▼ 基于Illumina和PacBio平台的“二加三”组装策略,巧妙的融合了PacBio平台超长读长 ...
- 安装Nvida 显示环境
查看是否能正确加载nvidia 驱动 在终端输入 (glxinfo 需要安装mesa-utils) 如果可以正确加载了nvidia驱动 那么在输入的内容中可以看到NVIDIA 字样 如果GPU是Int ...
- 关于Vue父组件把异步获取的数据传给子组件的问题
由于父组件中的数据是异步获取的,而子组件在一开始便会渲染,所以会造成子组件渲染完成后,数据还未获取到的情况 这里有一个简单的解决方案:在子组件渲染前,判断父组件数据是否获取完成,数据获取完成后再渲染子 ...
- JavaScript--关于闭包(closure)
js代码在执行前会做的几件事情: 1.代码检测 2.预编译:在执行代码之前会对代码中的函数以及变量提前声明 并且做一些其他的处理 1.函数在执行前的一瞬间,会生成一个OA(object action) ...
- sql查询并把数据更新到另一个表中
update OpenBills set peopleCount=(select rtNumber from Rooms where obId='ZD201005223') where obId='Z ...
- SAP Kyma(Extension Factory on SAP Cloud Platform)的架构简介
SAP kyma主要分三大块组成: (1) Application connector simplify and securely connect external systems to Kyma a ...
- [LeetCode] 22. 括号生成 ☆☆☆(回溯)
描述 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合. 例如,给出 n = 3,生成结果为: [ "((()))", "(()( ...
- vue组件间的传值方式及方法调用汇总
1.传值 a.父组件传子组件 方法一: 父页面: <myReportContent v-if="contentState==1" :paramsProps='paramsPr ...