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的文件,竟然只用了几秒钟,从带宽上限制可以得出,实际上传文件是不可能的 ...
随机推荐
- Django+Vue+Docker搭建接口测试平台实战
一. 开头说两句 大家好,我叫林宗霖,是一位测试工程师,也是全栈测开训练营中的一名学员. 在跟着训练营学习完Docker容器技术系列的课程后,理所应当需要通过实操来进行熟悉巩固.正好接口自动化测试平台 ...
- RandomForestClassifier参数
[RandomForestClassifier] 参数 n_estimators : 随机森林中树的个数,即学习器的个数. max_features : 划分叶子节点,选择的最大特征数目 n_feat ...
- mooc人大单元测试4
@font-face { font-family: Wingdings } @font-face { font-family: 宋体 } @font-face { font-family: " ...
- 【MySQL】Mysql(InnoDB引擎) 索引的数据结构为什么选择B+Tree
1.B+ Tree的层数较少 B类树的一个很鲜明的特点就是数的层数比较少,而每层的节点非常多,树的每个叶子节点到根节点的距离都是相同的: 2. 减少磁盘IO: 树的每一个节点都是一个数据也,这样每 ...
- 【Idea】实用的快捷键清单
1.Ctrl + Shift +i:快速查看某个类/方法 2.Ctrl +:(Ace Jump插件启动) 3.alt+F1:快速查看某个类/方法 所在的包 4.Ctrl +w :选中某个单词 5.Ct ...
- hdu1024 最大m子序列和
题意: 给你一个序列n个数组成,然后让你在里面找到m个子序列,让这m个子序列的和最大. 思路: dp[i][j]表示的是第j个数字在第i个子序列时的当前最优值. dp[i][j] ...
- 票据传递攻击(Pass the Ticket,PtT)
目录 黄金票据 生成票据并导入 查看票据 验证是否成功 黄金票据和白银票据的不同 票据传递攻击(PtT)是一种使用Kerberos票据代替明文密码或NTLM哈希的方法.PtT最常见的用途可能是使用黄金 ...
- 【JavaScript】Leetcode每日一题-二叉搜索树的范围和
[JavaScript]Leetcode每日一题-二叉搜索树的范围和 [题目描述] 给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和. 示例1: 输入: ...
- java之I/O流
I/O流的使用情况多种多样,首先它的数据源就可能是文件.控制台.服务器等,它的单位可能是按字节.按字符.按行等.为了涵盖所有的可能,java类库中创建了大量的类,如此多的类让我们在使用时感觉有点难以选 ...
- 解决移动端300ms延迟fastclick
为什么要使用fastclick 移动设备上的浏览器默认会在用户点击屏幕大约延迟300毫秒后才会触发点击事件,这是为了检查用户是否在做双击.为了能够立即响应用户的点击事件,才有了fastclick. f ...