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的文件,竟然只用了几秒钟,从带宽上限制可以得出,实际上传文件是不可能的 ...
随机推荐
- MySql 按日,按周,按月 分组 统计数据
知识关键词:DATE_FORMAT 按天统计: SELECT DATE_FORMAT(create_time,'%Y%m%d') days, COUNT(caseid) count FROM tc_c ...
- 病毒木马查杀实战第017篇:U盘病毒之专杀工具的编写
前言 经过前几次的讨论,我们对于这次的U盘病毒已经有了一定的了解,那么这次我们就依据病毒的行为特征,来编写针对于这次U盘病毒的专杀工具. 专杀工具功能说明 因为这次是一个U盘病毒,所以我打算把这次的专 ...
- hdu3336 KMP + DP 前缀数组出现的次数
题意: 给你一个串,问你他的所有前缀子串在本串中的出现次数,注释:abc的前缀子串是 a ab abc; 思路: 还是利用了next数组,先对子串求出next数组,再开一个数组d ...
- Linux中Nginx服务器的部署和配置
目录 Nginx安装方式: yum源安装 目录结构: 源码包安装 目录结构: Nginx中支持PHP Nginx中配置php对mysql数据库的支持 Nginx配置反向代理服务器 正常代理 根据不同端 ...
- Nessus扫描器的使用
目录 Nessus Scans Settings 一个基本扫描的建立 自定义扫描策略 Nessus的高级扫描方法 Nessus Nessus号称是世界上最流行的漏洞扫描程序,全世界有超过75000个组 ...
- POJ2296二分2sat
题意: 给n个点,每个点必须在一个正方形上,可以在正方向上面边的中点或者是下面边的中点,正方形是和x,y轴平行的,而且所有的点的正方形的边长一样,并且正方形不能相互重叠(边相邻可以),问满 ...
- 关于YiII框架的扩展memcache中set设置时间就get查询失效的解决方案(版本是1.1.20)
0x01 前言 在使用Yii框架的扩展memcache缓存的时候,存储数据有一个set方法,来看一下set方法的原型: public boolean set(string $id, mixed $va ...
- Win64 驱动内核编程-7.内核里操作进程
在内核里操作进程 在内核里操作进程,相信是很多对 WINDOWS 内核编程感兴趣的朋友第一个学习的知识点.但在这里,我要让大家失望了,在内核里操作进程没什么特别的,就标准方法而言,还是调用那几个和进程 ...
- src/main/resorces applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- Java 中 RMI 的使用
RMI 介绍 RMI (Remote Method Invocation) 模型是一种分布式对象应用,使用 RMI 技术可以使一个 JVM 中的对象,调用另一个 JVM 中的对象方法并获取调用结果.这 ...