第一步:发送文件

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. struts_19_对Action中所有方法、某一个方法进行输入校验(手工编写代码实现输入校验)

    对所有方法进行校验1.通过手工编写代码的形式实现 需求:用户名:不能为空手机号:不能为空,并且要符合手机号的格式1,3/5/8,后面是9个数字 第01步:导包 第02步:配置web.xml <? ...

  2. WebForm中<%=%>与<%#%>的区别?

    1<%=%>相当于Response.Write(),是输出变量的值 2<%#%>专门用于数据绑定,可以绑定一些变量或者数据源中的信息,中间绑定是数据源的条目,若想让它起作用,必 ...

  3. 夺命雷公狗—angularjs—22—bind改指向和传参方式

    在angularjs中的传参的jquery的方式是极度相似的噢,而且还可以通过bind来改变指向 <!DOCTYPE html> <html lang="en" ...

  4. 初级node+express建站

    我的建站经历. 我建站的原因也很简单,就仅仅想有一个linux服务器玩一玩,但是还没有想到要怎么玩,就先搭建一个web服务吧.因为我工作的时候可能会用到. 我就从头开始讲起走. 先买了个云服务器,选择 ...

  5. 写sql语句分别按日,星期,月,季度,年统计

    --写sql语句分别按日,星期,月,季度,年统计销售额 --按日 ' group by day([date]) --按周quarter ' group by datename(week,[date]) ...

  6. Linux/Unix中的#!和!#

    是不是在Terminal输入命令的时候,输入了很长的一个路径,然后发现还有在同一条命令中再输一次的时候很恼火,其实Shell是提供了trick的,就是使用!#(和#!不同哦) 习惯写脚本的猿,通常对于 ...

  7. zabbix源码安装

    Zabbix通过C/S模式采集数据,通过B/S模式在web端展示和配置. 被监控端:主机通过安装agent方式采集数据,网络设备通过SNMP方式采集数据 Server端:通过收集SNMP和agent发 ...

  8. android listview万能适配器

    参考    Android 快速开发系列 打造万能的ListView GridView 适配器 Hongyang public class CommonViewHolder { private Con ...

  9. linux下共享内存mmap和DMA(直接访问内存)的使用 【转】

    转自:http://blog.chinaunix.net/uid-7374279-id-4413316.html 介绍Linux内存管理和内存映射的奥秘.同时讲述设备驱动程序是如何使用“直接内存访问” ...

  10. 为什么你要拒绝我 ——苹果AppStore被拒理由大全

    简而言之 截图中出现了Android 截图中出现了hack苹果的内容 评论中出现了"屌丝"等不雅词汇 App中包含谈论Android系统的内容 你修改了状态栏,不行 只有第三方登录 ...