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的文件,竟然只用了几秒钟,从带宽上限制可以得出,实际上传文件是不可能的 ...
随机推荐
- kubernetes的Deployment, DaemonSet, Job 和 CronJob事例
k8s kubernetes给node节点添加标签和删除node节点标签 Deployment配置文件exampledeploymentv1.yaml apiVersion: apps/v1 kind ...
- Java双刃剑之Unsafe类详解
前一段时间在研究juc源码的时候,发现在很多工具类中都调用了一个Unsafe类中的方法,出于好奇就想要研究一下这个类到底有什么作用,于是先查阅了一些资料,一查不要紧,很多资料中对Unsafe的态度都是 ...
- misdirection靶机work_through
web打点 nmap扫描 Nmap scan report for 192.168.218.135 Host is up (0.000014s latency). Not shown: 65531 c ...
- Nginx 负载均衡方案
轮询 根据Nginx配置文件中的顺序,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除. upstream web { server server1; serve ...
- 【多线程】Java线程池七个参数详解
/** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters. * * @param coreP ...
- 子域名查询、DNS记录查询
目录 子域名信息查询 Layer子域名爆破机 subDomainBrute 利用google查询 HTTP证书查询 DNS记录查询脚本 IP转换为经纬度 利用网页获取对方经纬度信息 首先关于DNS域名 ...
- Windows中的用户和组以及用户密码处理
目录 用户帐户 Windows 默认账户 Windows 内置用户账户 查看.创建和删除账户 组账户 内置组账户 组的查看.创建和删除 Windows中对用户密码的处理 LM-hash NTLM-ha ...
- 【Unity】实验二 游戏场景搭建
实验要求 实验二 游戏场景搭建 实验目的:掌握游戏场景搭建. 实验要求:能够使用Unity的地形引擎创建地形,熟悉场景中的光照与阴影,掌握天空盒和雾化效果等. 实验内容: 地形的绘制:使用高度图绘制: ...
- SpringBoot程序后台运行
使用nohup命令让进程后台运行 nohup java -jar 自己的springboot项目.jar >日志文件名.log 2>&1 & >日志文件名.log : ...
- 【实用小技巧】Access denied for user 'root'@'localhost' 报错解决
到mysql安装目录修改my.ini文件,在文件末尾追加一句 skip-grant-tables 然后重启mysql服务即可