Go语言网络通信---tcp上传大文件(粘包问题还需优雅解决)
server端:
package main import (
"bufio"
"encoding/binary"
"fmt"
"net"
"os"
"unsafe"
) func SHandleError(err error, when string) {
if err != nil{
fmt.Println("服务端异常退出,err=", err, when)
os.Exit(1)
}
} func BytesToInt64(buf []byte) int64 {
return int64(binary.BigEndian.Uint64(buf))
} func main() {
//建立tcp监听
listener, e := net.Listen("tcp", ":8080")
SHandleError(e, "net.Listen")
defer func() {
listener.Close()
fmt.Println("服务端正常退出")
}() //接受客户端请求,建立会话专线Conn
conn, e := listener.Accept()
SHandleError(e, "listener.Accept")
defer func() {
conn.Close()
fmt.Printf("已断开与%v的链接\n", conn.RemoteAddr())
}() dstFile, e := os.OpenFile(`meinv1.mp4`, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
writer := bufio.NewWriter(dstFile)
defer dstFile.Close()
buffer := make([]byte, 100)
total := 0 //接受客户端发来的要传文件大小
buffer2 := make([]byte, 10)
m, e := conn.Read(buffer2)
//size := string(buffer2[:m])
//fmt.Printf("%s\n",size)
//i, _ := strconv.Atoi(size) //[]byte转换为int64
i := BytesToInt64(buffer2[:m])
fmt.Printf("%d, %T\n",i,i)
//int64转换为int
j := *(*int)(unsafe.Pointer(&i))
fmt.Printf("%d, %T\n",j,j) for {
//接受客户端上传的文件
n, e := conn.Read(buffer)
SHandleError(e, "conn.Read")
total += n //写入服务端本地文件
writer.Write(buffer[:n])
writer.Flush() fmt.Printf("成功写入%d个字节,共%d字节\n", n, total) //如果实际总接受字节数与客户端给的要传输字节数相等,说明传输完毕
if total == j{
fmt.Println("文件接受成功,共",total,"字节")
//回复客户端已收到文件
conn.Write([]byte("文件接受成功"))
break
}
}
}
client端:
package main import (
"bufio"
"encoding/binary"
"fmt"
"io"
"net"
"os"
"time"
) /*
·实现tcp文件上传功能
*/ func CHandleError2(err error, when string) {
if err != nil {
fmt.Println("客户端异常退出:err=", err, when)
os.Exit(1)
}
}
func Int64ToBytes(i int64) []byte {
var buf = make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
return buf
}
func main() {
conn, e := net.Dial("tcp", "127.0.0.1:8080")
CHandleError2(e, "net.Dial") defer func() {
conn.Close()
fmt.Println("客户端正常退出")
}() //获取目标文件的大小,传给服务端
fileInfo, _ := os.Stat(`perfect.mp4`)
size := fileInfo.Size()
bytes := Int64ToBytes(size)
conn.Write(bytes) //暂时通过客户端sleep 200毫秒解决粘包问题,还可以通过tcp重连解决,以后再用(包头+数据)封装数据包的方式解决
time.Sleep(time.Millisecond * 200) buffer := make([]byte, 100)
srcFile, _ := os.Open(`perfect.mp4`)
reader := bufio.NewReader(srcFile)
total := 0
for {
n, err := reader.Read(buffer)
fmt.Println(n, err)
if err == io.EOF{
fmt.Println("文件发送完毕")
fmt.Println(total)
break
}else {
_, e = conn.Write(buffer[:n])
total += n
CHandleError2(e, "conn.Write")
}
} n, e := conn.Read(buffer)
CHandleError2(e, "conn.Read")
replyMsg := buffer[:n]
fmt.Println("服务端:", string(replyMsg))
}
Go语言网络通信---tcp上传大文件(粘包问题还需优雅解决)的更多相关文章
- tcp上传大文件举例、udp实现qq聊天、socketserver模块实现并发
为什么会出现粘包现象(day31提到过,这里再举个例子) """首先只有在TCP协议中才会出现粘包现象,因为TCP协议是流式协议它的特点是将数据量小并且时间间隔比较短的数 ...
- [Asp.net]Uploadify上传大文件,Http error 404 解决方案
引言 之前使用Uploadify做了一个上传图片并预览的功能,今天在项目中,要使用该插件上传大文件.之前弄过上传图片的demo,就使用该demo进行测试.可以查看我的这篇文章:[Asp.net]Upl ...
- php 上传大文件配置upload_max_filesize和post_max_size选项
php 上传大文件配置upload_max_filesize和post_max_size选项 (2014-04-29 14:42:11) 转载▼ 标签: php.ini upload _files[f ...
- PHP上传大文件 分割文件上传
最近遇到这么个情况,需要将一些大的文件上传到服务器,我现在拥有的权限是只能在一个网页版的文件管理系统来进行操作,可以解压,可以压缩,当然也可以用它来在线编辑.php文件. 文件有40M左右,但是服务器 ...
- ASP.NET上传大文件的问题
原文:http://www.cnblogs.com/wolf-sun/p/3657241.html?utm_source=tuicool&utm_medium=referral 引言 之前使用 ...
- php 上传大文件主要涉及配置upload_max_filesize和post_max_size两个选项
php 上传大文件主要涉及配置 upload_max_filesize 和post_max_size两个选项 今天在做上传的时候出现一个非常怪的问题,有时候表单提交可以获取到值,有时候就获取不到了 ...
- SWFUpload上传大文件(暂时用用,真正用的时候还是要改的)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- PHP上传大文件和处理大数据
1. 上传大文件 /* 以1.5M/秒的速度写入文件,防止一次过写入文件过大导致服务器出错(chy/20150327) */ $is_large_file = false; if( strlen($x ...
- QQ上传大文件为什么这么快
今天和同事在群里讨论“QQ上传大文件/QQ群发送大文件时,可以在极短的时间内完成”是如何做到的. 有时候我们通过QQ上传一个几百M的文件,竟然只用了几秒钟,从带宽上限制可以得出,实际上传文件是不可能的 ...
随机推荐
- grafana接入zabbix数据源
一.grafana介绍 grafana是开源免费的应用数据可视化仪表盘,由于zabbix本身对监控数据可视化并不侧重,所以大多使用第三方数据可视化工具来做大屏.下面向小伙伴们介绍grafana接入za ...
- 如何在linux上手动连接到互联网
作者 @飞洲人飞舟魂转载请注明出处. 一直以来对linux的网络管理不大明白,今天研究了一下网络的手动配置,现在记录一下.我使用Ubuntu20.04.1来进行演示. 介绍 首先我们先明确一些概念性的 ...
- http文件下载与404
# http文件下载与404 if (!file_exists($file_path)) { header('HTTP/1.1 404 Not Found'); header("status ...
- hdu2435最大流最小割
2435 There is a war 题意: 给你一个有向图,其中可以有一条边是无敌的,这条边可以是图中的边,也可以是自己任意加上去的图中没有的边,这条无敌的边不可以摧毁,让1和n无法 ...
- POJ1679判断最小生成树的唯一性
题意: 判断最小树是否唯一. 思路: 我用了两种方法,主要就是好久没敲了,找个水题练练手,第一种就是先一遍最小生成树,然后枚举最小生成树上的每一条边,然后取消这条边,在跑一遍最小生 ...
- Linux(CentOS-8)安装MySQL8.0.11
CentOS安装MySQL8.0.11 总的思路就是:安装MySQL,编写配置文件,配置环境变量,成功开启服务,登陆并修改ROOT密码 开启远程访问的思路就是:授权用户所有IP都可以访问,系统的数据库 ...
- IO异步,读写压缩文件,监控文件系统
这节结尾IO,讲一下异步操作文件,读写压缩文件,监控文件系统这三个知识点. 异步操作文件: 说到异步,必然要了解的是async和await这两个关键字(异步详情点击基于任务的异步编程(Task ...
- Java_继承
继承的格式 继承它描述的是两个类之间的关系,如果一个子类继承父类,那么子类可以使用父类非私有的成员. 1 public class 父类{ 2 //成员变量 3 //成员方法 4 } 5 6 publ ...
- BUAA OS实验调试指南:从看懂到看开
一般的调试流程其实很简单:发现问题,稳定复现,确定临界条件,定位问题,修复问题,核查结果.迭代这个过程,形成一个闭环 老实说,OS的实验代码,开箱体验极差,程序跳来跳去,进了Lab4后还要考虑内核态切 ...
- 《前端运维》一、Linux基础--02用户与权限
其实说真的,这些基础挺枯燥的,内容呢绝大多数都是些静态的. 上一篇文章我们学习了基本的指令和vim编辑器的操作方法.这篇文章我们主要来学习下Linux中用户的概念和权限相关的知识. 一.用户与用户组 ...