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语言 功能:文件传输(可以传任何格式的文件) /******************************************** ...
随机推荐
- MYSQL编码转换的问题latin1转utf8
1.先导出 mysqldump --default-character-set=latin1 --create-options=false --set-charset=false -u root - ...
- FlowPortal BPM 明细表中新添加的行一直排在最后的问题
明细表中的数据提交过之后再编辑时,添加的行不管在第几行添加都显示在最后一行的问题 Solution:明细表的数据库表中加字段OrderIndex,设为必填,系统会自动排序
- string leetcode-6.ZigZag
6. ZigZag Conversion 题面 The string "PAYPALISHIRING" is written in a zigzag pattern on a gi ...
- 为什么JAVA线程中没有Running状态?
面试官问:为什么 Java 线程没有 Running 状态?我懵了 —— 转 芋道源码 什么是 RUNNABLE? 与传统的ready状态的区别 与传统的running状态的区别 当I/O阻塞时 如 ...
- Android 启动流程分析
原文:https://www.jianshu.com/p/a5532ecc8377 作者曾经在高通的Android性能组工作,主要工作是优化Android Application的启动时间. APP基 ...
- MySQL在使用group_concat()函数数据被截取
遇到问题: 项目中有个需求,MySQL中存储的是树状的数据.现在给出一个节点,需要从Mysql数据库中取出这个节点下所有的节点.采用MySQL的函数. 函数如下: CREATE DEFINER=`ro ...
- 向量的一种特殊乘法 element wise multiplication
向量的一种特殊乘法 element wise multiplication 物体反射颜色的计算采用这样的模型: vec3 reflectionColor = objColor * lightColor ...
- idou老师教你学Istio11 : 如何用Istio实现流量熔断
在之前的最佳实践中,已经带大家通过一系列的实践任务领略了Istio的无穷魅力.今天,将向大家介绍如何用Istio实现流量熔断. 熔断机制是创建弹性微服务应用程序的重要模式.熔断可以帮助您自由控制故障影 ...
- .netFramework中新增的功能—.net最新信息—.net的发展
关键字:.NET Framework 中的新增功能 链接地址:https://docs.microsoft.com/zh-cn/dotnet/framework/whats-new/index 链接地 ...
- 将自己写的组件封装成类似element-ui一样的库,可以cdn引入
在写好自己的组件之后 第一步 修改目录结构 在根目录下创建package文件夹,用于存放你要封装的组件 第二部 在webpack配置中加入 pages与publicpath同级 pages: { in ...