服务端实现流程大致如下:

  1. 创建监听listener,程序结束时关闭。
  2. 阻塞等待客户端连接,程序结束时关闭conn。
  3. 读取客户端发送文件名。保存fileName。
  4. 回发“ok”给客户端做应答
  5. 封装函数 RecvFile接收客户端发送的文件内容。传参fileName 和conn
  6. 按文件名Create文件,结束时Close
  7. 循环Read客户端发送的文件内容,当读到EOF说明文件读取完毕。
  8. 将读到的内容原封不动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)
}
}

客户端实现流程大致如下:

  1. 提示用户输入文件名。接收文件名path(含访问路径)
  2. 使用os.Stat()获取文件属性,得到纯文件名(去除访问路径)
  3. 主动连接服务器,结束时关闭连接
  4. 给接收端(服务器)发送文件名conn.Write()
  5. 读取接收端回发的确认数据conn.Read()
  6. 判断是否为“ok”。如果是,封装函数SendFile() 发送文件内容。传参path和conn
  7. 只读Open文件, 结束时Close文件
  8. 循环读文件,读到EOF终止文件读取
  9. 将读到的内容原封不动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文件传输的更多相关文章

  1. 艺萌TCP文件传输及自动更新系统介绍(TCP文件传输)(四)

    艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开源,作者是英国的,开发时间5年多,框架很稳定. 项 ...

  2. 艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输)(一)

    艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开元,作者是英国的,开发时间5年多,框架很稳定. 项 ...

  3. qt+boost::asio+tcp文件传输

    客户端: void qt_boost::pbSendFileClicked(){ QString filename = ui.leFileName->text(); QByteArray ba ...

  4. Java 简单TCP文件传输

    服务端 package TCP; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputSt ...

  5. python基础实现tcp文件传输

    准备工作,实现文件上传需要那些工具呢? socket(传输).open()(打开文件).os(读取文件信息),当然还有辅助类sys和json,下面我们开始吧 import socket,sys imp ...

  6. Java Tcp文件传输---转载

    /** 客户端 1.服务端点 2.读取客户端已有的文件数据 3.通过socket输出流发给服务端 4.读取服务端反馈信息 5.关闭 **/ import java.io.*; import java. ...

  7. 在TCP文件传输中如何判断java流的末尾

    感谢前辈们的解答:https://bbs.csdn.net/topics/280085530 问题描述: 服务端向客户端发送数据流,服务端发完了数据不关闭流. 我在客户端读流,我无法读到-1,所以无法 ...

  8. Linux网络编程:socket文件传输范例

    基于TCP流协议的socket网络文件传输Demo: 实现:C语言功能:文件传输(可以传任何格式的文件) /********************************************** ...

  9. Windows网络编程:winsock文件传输范例

    基于TCP流协议的winsock网络文件传输Demo: 实现:C语言 功能:文件传输(可以传任何格式的文件) /******************************************** ...

随机推荐

  1. asp.net类似于js中的setTimeOut()的函数作用?

    asp.net类似于js中的setTimeOut()的函数作用? 插入这行即可,定时2秒,再运行下一步: System.Threading.Thread.Sleep(); 加个随机数 Random r ...

  2. D盘Program Files 文件夹里文件不显示,没隐藏。怎么才能显示出来?

    D盘里有两个一模一样的Program Files 文件夹,文件夹里文件不显示,没隐藏.怎么才能显示出来?新买不久的电脑,win8.1系统 点击开始---运行---输入“cmd”(没有引号)---在弹出 ...

  3. 解析Illumina+PacBio组装策略

    解析Illumina+PacBio组装策略 (2016-12-08 13:21:58) 转载▼     基于Illumina和PacBio平台的“二加三”组装策略,巧妙的融合了PacBio平台超长读长 ...

  4. 安装Nvida 显示环境

    查看是否能正确加载nvidia 驱动 在终端输入 (glxinfo 需要安装mesa-utils) 如果可以正确加载了nvidia驱动 那么在输入的内容中可以看到NVIDIA 字样 如果GPU是Int ...

  5. 关于Vue父组件把异步获取的数据传给子组件的问题

    由于父组件中的数据是异步获取的,而子组件在一开始便会渲染,所以会造成子组件渲染完成后,数据还未获取到的情况 这里有一个简单的解决方案:在子组件渲染前,判断父组件数据是否获取完成,数据获取完成后再渲染子 ...

  6. JavaScript--关于闭包(closure)

    js代码在执行前会做的几件事情: 1.代码检测 2.预编译:在执行代码之前会对代码中的函数以及变量提前声明 并且做一些其他的处理 1.函数在执行前的一瞬间,会生成一个OA(object action) ...

  7. sql查询并把数据更新到另一个表中

    update OpenBills set peopleCount=(select rtNumber from Rooms where obId='ZD201005223') where obId='Z ...

  8. SAP Kyma(Extension Factory on SAP Cloud Platform)的架构简介

    SAP kyma主要分三大块组成: (1) Application connector simplify and securely connect external systems to Kyma a ...

  9. [LeetCode] 22. 括号生成 ☆☆☆(回溯)

    描述 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合. 例如,给出 n = 3,生成结果为: [ "((()))", "(()( ...

  10. vue组件间的传值方式及方法调用汇总

    1.传值 a.父组件传子组件 方法一: 父页面: <myReportContent v-if="contentState==1" :paramsProps='paramsPr ...