第一步:发送文件

FILE* pSENDFILE = _wfopen(m_edit_chosefile, _T("rb"));//以二进制打开待发送文件的的文件指针
fseek(pSENDFILE, 0, SEEK_END);
int len = ftell(pSENDFILE);//获得待发送文件总长度,2的32次方=2G
fseek(pSENDFILE, 0, SEEK_SET);

if (len > (30 * 1024 * 1024))//如果待发送文件大于30M
{

int bigloop = len / (30 * 1024 * 1024);//一共有bigloop个30M
int bigremain = len % (30 * 1024 * 1024);//发送bigloop个30M之后还bigremain个字节
for (int i = 0; i < bigloop; i++)//每次循环发送30M,循环结束代表发送完成了bigloop次30M文件
{
BYTE ByteBuf_1K[1 * 1024];//每次读取文件buf为1k
CByteArray ByteArray_1K;//每次发送文件array为1k
ByteArray_1K.SetSize(1 * 1024);
for (int j = 0; j < (30 * 1024); j++)//这个循环实现发送30M文件
{
  fread(ByteBuf_1K, 1 * 1024, 1, pSENDFILE);//从文件读取1k数据到buf中
  for (int k = 0; k < 1 * 1024; k++)
  ByteArray_1K.SetAt(k, ByteBuf_1K[k]);//把buf的1k数据转化为十六进制到array中,用于串口发送
  m_mscomm.put_Output((COleVariant)ByteArray_1K);//发送

  Sleep(2);//等待接收端接收
}
Sleep(2000);//等待接收端写30M数据到文件中
}
/*发送bigloop次30M之后,如果剩余数据大于1K*/
if (bigremain > 1 * 1024)
{

int smallloop = bigremain / (1 * 1024);//需要发送loop次
int smallremain = bigremain % (1 * 1024);///发送loop次之后还剩remain个字节
BYTE ByteBuf_1K[1 * 1024];//这个buf用来存从待发送文件独读出来的数据
CByteArray ByteArray_1K;//这个array用来存待发送文件十六进制数据
ByteArray_1K.SetSize(1 * 1024);//一次发送1k数据
for (int i = 0; i < smallloop; i++)
{
fread(ByteBuf_1K, 1 * 1024, 1, pSENDFILE);//把待发送文件的第loop个4k以二进制读取在buf里
for (int k = 0; k < (1 * 1024); k++)
ByteArray_1K.SetAt(k, ByteBuf_1K[k]);//把buf里的字符以十六进制存在array里
m_mscomm.put_Output((COleVariant)ByteArray_1K);//发送
Sleep(2);//等待接收方写文件所需时间,否则会有乱码;这个时间过大会阻塞,过小会丢包
}
/*发送剩余的smallremain个字节*/
BYTE *bufremain;
bufremain = new BYTE[smallremain];//new1个数组,发送剩余数据
CByteArray arrayremain;//装剩余数据的十六进制
arrayremain.SetSize(smallremain);
fread(bufremain, smallremain, 1, pSENDFILE);//读取剩余数据
for (int l = 0; l < smallremain; l++)//转换数据为CByteArray类型
arrayremain.SetAt(l, bufremain[l]);
m_mscomm.put_Output((COleVariant)arrayremain);//发送剩余数据
Sleep(200);//短暂休眠
delete bufremain;//回收bufremain
fclose(pSENDFILE);//关闭文件指针
}
/*发送bigloop次30M之后,如果剩余数据小于1K*/
else
{

BYTE *buf;
buf = new BYTE[bigremain];//new一个buf来存从文件指针读取的数据
fread(buf, bigremain, 1, pSENDFILE);//读取待发送文件数据,存在buf里面
CByteArray array;//用来保存发送数据的十六进制形式
array.SetSize(bigremain);//给array设置大小,这个大小为待发送文件的字节数
for (int m = 0; m < bigremain; m++)
array.SetAt(m, buf[m]);//数据转十六进制
m_mscomm.put_Output((COleVariant)array);//发送数据
Sleep(200);//短暂睡眠,可以不取
delete buf;//回收
array.RemoveAll();//关闭文件指针
fclose(pSENDFILE);
}
}

过程:上面的程序只是发送文件大概的过程,没有写得很详细,本人觉得思想是最重要的,代码写得来没有算法懂得来好。

   首先发送端发送文件大小,通过一定编码,如加入特殊包头,接收端解码,获得文件大小;

   判断文件是否大于30M,当大于30M,算得有多少个30M,多少个30M后还剩余多少,这里用除法和取余的方式。

   一个循环,发送多少个30M,这里有个小循环,为了不丢包,一次实际发送1k数据,发送30*1024次就发送完了30M。

    走到了这一步,后面就简单了,就不赘述了。

第二步:接收文件

variant = m_mscomm.get_Input();//从接收缓冲区获得的数据是variant结构体类型数据
colesafearray = variant;

long len, k;
len = colesafearray.GetOneDimSize();//获取缓冲区长度
for (k = 0; k < len; k++)
{

  colesafearray.GetElement(&k, bigBuf + c);//把缓冲区的数据写到bigbuf里
  c++;
  count_all++;
  if (c == (30 * 1024 * 1024 - 1))//如果10M接收完成
    {
    fwrite(bigBuf, c, 1, pFILE);//写入10M数据到文件
    fflush(pFILE);//刷新
    c = 0;//重新接收
    }
  if (count_all == file_all)//如果已经接收到了发送文件大小个字节,代表发送和接收完成
    {
  fwrite(bigBuf, c, 1, pFILE);//写入10M数据到文件
  fclose(pFILE);//关闭接收文件指针
  delete bigBuf;//回收缓冲区内存
  c = 0;//重置c
  count_all = 0;//重置count_all
  AfxMessageBox(_T("receive succes"));//弹出对话框表示接收成功

    }
}

过程:事先从发送端发送目标文件字节数到接收端,接收端定义两个int c和count_all都等于0;

接收端每处理一个字节的数据到缓冲区,c和count_all++:

    当c=30M时,写入到本地文件,然后c置0;

    当count_all=目标文件大小时,再写,回收内存。

ps:

1、现象:使虚拟串口连接com1和com2,在com1的oncomm事件开头加一个断点,当另一个串口助手连接com2时,程序在断点停止。
猜想:当com1和com2连接的时候,两个串口会互相发出数据。由于在com1的设置中,当接收缓冲区有数据时会触发oncomm事件,故有此现象。应该是类似握手的数据,以判断两个串口是否连接在一起。

2、现象:发送大于4k数据时,接收端都只能接收到4096字节即4k数据,小于4k时正常。
猜想:发送和接收数据,是一个主动和被动的过程,假如com1发送1个G的数据到com2,此时如果com1全部把1G数据放在发送缓冲区,而com2可能由于一些状况比如操作系统缓慢,那就会造成发送的多而接收的少,结果就是掉包,所以我估计微软为了更好的的传送数据,就让我的com1一次只能发送4k数据。

3、现象:网上很多人说,设置这句话put_RThreshold(1),表示接收缓冲区每有1个或者大于1个数据的时候就会触发oncomm事件(oncomm事件其实是一个线程),然而我进入oncomm事件调试,发现安全数组的GetOneDimSize总是返回发送文件的字节大小,而不是等于1或着大于1的不确定的数。
猜想:由于计算机速度太快,com1的4k数据太快就到了com2缓冲区,com2的get_Input里自动装了全部4k数据,所以可以把串口通信想象成这样一个简单的过程:
com1把4k数据慢慢放进发送缓冲区---->com1的发送缓冲区慢慢把数据传输到com2的接收缓冲区---->此时微软悄悄把接收缓冲区的数据放在get_Input里---->然后这是com2发现接收缓冲区里有数据,产生oncomm事件,此时所有数据都被微软放在了get_Input里---->用户在oncomm事件里处理数据。
我估计这sb微软把上面com2接收缓冲区里的数据自动存起来,不需要用户再去处理,只需要用户在oncomm里处理数据。然而我因为网上的回答“put_RThreshold(1),表示接收缓冲区每有1个或者大于1个数据的时候就会触发oncomm事件”懵逼了两天,调试结果就是和自己想不一样,所以也就骂了两天微软。

4、为何我电脑后台软件开多了,会有丢包的现象?

猜想:由于发送端和接收端都是线程函数,当pc线程多了之后,就会占用我们这两个线程,发送端线程被占用之后还好,当接收端被占用了,而此时如果发送端还在发送,可能很短

的时间,但是电脑速度极快,这一点点的时间差可能发送端已经走了几个发送1k数据的循环了,而此时接收端正被阻塞着,这是就丢包了。由于我这程序的设计思想,只要丢包了1个字节以上,那么最终导致丢(总字节数%30M)个字节。所以,必须保证不能丢一个字节数据。

解决:把发送端线程函数线程优先级设置为最低。这样可以一定程度解决丢包问题,因为当pc需要阻塞线程的时候,会首先占用发送端的线程,而发送端线程被占用是不会影响丢包的。但是,如果线程多的抠脚,理论上接收端也可能被阻塞的,只要接收端被阻塞,发送端没有被阻塞,就一定会丢包。所以,理论上是不能完全解决这个问题的,除非你电脑内核比线程多哈哈哈哈。

使用MSCOMM发送任意文件,还有一些注意事项的更多相关文章

  1. 代码审计之XiaoCms(后台任意文件上传至getshell,任意目录删除,会话固定漏洞)

    0x00 前言 这段时间就一直在搞代码审计了.针对自己的审计方法做一下总结,记录一下步骤. 审计没他,基础要牢,思路要清晰,姿势要多且正. 下面是自己审计的步骤,正在逐步调整,寻求效率最高. 0x01 ...

  2. [代码审计]phpshe开源商城后台两处任意文件删除至getshell

    0x00 背景 这套系统审了很久了,审计的版本是1.6,前台审不出个所以然来.前台的限制做的很死. 入库的数据都是经过mysql_real_escape_string,htmlspecialchars ...

  3. [代码审计]XiaoCms(后台任意文件上传至getshell,任意目录删除,会话固定漏洞)

    0x00 前言 这段时间就一直在搞代码审计了.针对自己的审计方法做一下总结,记录一下步骤. 审计没他,基础要牢,思路要清晰,姿势要多且正. 下面是自己审计的步骤,正在逐步调整,寻求效率最高. 0x01 ...

  4. 17.[CVE-2017-12615]Tomcat任意文件上传漏洞

    [CVE-2017-12615] Tomcat任意文件上传漏洞 首先先贴出wooyun上的一个案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2015-0 ...

  5. ActiveMQ反序列化(CVE-2015-5254) && ActiveMQ任意文件写入 (CVE-2016-3088)

    ActiveMQ 反序列化漏洞(CVE-2015-5254) 漏洞详情 ActiveMQ启动后,将监听61616和8161两个端口,其中消息在61616这个端口进行传递,使用ActiveMQ这个中间件 ...

  6. PHP:网展cms后台任意文件删除和sql注入

    0x01:目录结构 可以发现Frameword是框架的文件 install安装 public公共文件 uploads储存上传之类的文件 webuser后台文件 Home前台文件 0x02.csrf漏洞 ...

  7. Wordpress4.9.6 任意文件删除漏洞复现分析

    第一章 漏洞简介及危害分析 1.1漏洞介绍 WordPress可以说是当今最受欢迎的(我想说没有之一)基于PHP的开源CMS,其目前的全球用户高达数百万,并拥有超过4600万次的超高下载量.它是一个开 ...

  8. mysql任意文件读取漏洞复现

    前言 第一次得知该漏洞后找了一些文章去看. 一开始不明白这个漏洞是怎么来的,只知道通过在服务端运行poc脚本就可以读取客户端的任意文件,直接找到网上准备好的靶机进行测试,发现可行,然后就拿别人的poc ...

  9. CVE-2020-3452 CISCO ASA远程任意文件读取漏洞

    0x01 漏洞描述     Cisco官方 发布了 Cisco ASA 软件和 FTD 软件的 Web 接口存在目录遍历导致任意文件读取 的风险通告,该漏洞编号为 CVE-2020-3452.     ...

随机推荐

  1. 变形--扭曲 skew()

    变形--扭曲 skew() 扭曲skew()函数能够让元素倾斜显示.它可以将一个对象以其中心位置围绕着X轴和Y轴按照一定的角度倾斜.这与rotate()函数的旋转不同,rotate()函数只是旋转,而 ...

  2. ios 开源代码

    .开源代码 http://www.oschina.net/iOS/codingList/365/ios-button http://www.devdiv.com/iOS_iPhone-iOS6%E6% ...

  3. (转)【ASP.NET开发】获取客户端IP地址 via C#

    [ASP.NET开发]获取客户端IP地址 via C# 说明:本文中的内容是我综合博客园上的博文和MSDN讨论区的资料,再通过自己的实际测试而得来,属于自己原创的内容说实话很少,写这一篇是为了记录自己 ...

  4. Spark K-Means

    K-Means(K均值) 介绍 K-Means是被应用的最广泛的基于划分的聚类算法,是一种硬聚类算法,属于典型的局域原型的目标函数聚类的代表.算法首先随机选择k个对象,每个对象初始地代表一个簇的平均值 ...

  5. linux时区的设置

    到目前为止,个人的理解就是linux中设置时区就是修改配置文件 /etc/localtime 而通常的做法就是让这个文件作为符号链接,链接到 /usr/share/zoneinfo/ 中的某个特定的时 ...

  6. Bootstrap之Carousel问题

    一.不能自动播放的解决办法 1.默认使用Bootstrap的Carousel组件,只需要加上 data-ride="carousel" 就可以实现自动播放了.无需使用初始化的js函 ...

  7. mmap DMA【转】

    转自:http://blog.csdn.net/lihaoweiv/article/details/6275241 第 13 章  mmap 和 DMA 本章将深入探讨 Linux 内存管理部分,并强 ...

  8. linux内核栈用户栈切换【转】

    转自:http://www.kerneltravel.net/kernel-book/%E7%AC%AC%E5%9B%9B%E7%AB%A0%20%E8%BF%9B%E7%A8%8B%E6%8F%8F ...

  9. Linux驱动开发 -- 打开dev_dbg() 【转】

    转自:http://blog.chinaunix.net/uid-20672559-id-3383042.html linux设备驱动调试,我们在内核中看到内核使用dev_dbg来控制输出信息,这个函 ...

  10. iOS抓包Charles 操作

    今天就来看一下Mac上如何进行抓包,之前有一篇文章介绍了使用Fidder进行抓包 http://blog.csdn.net/jiangwei0910410003/article/details/198 ...