MFC大文件传输
MFC大文件传输核心思想(C/C++程序员之家自己研究的,请大家指出不当之处,以便更正):
首先先给下CSDN上论坛对TCP大文件传输的讨论:
TCP发送端速度过快,有可能造成堵塞,发送缓冲区满之后就会丢数据,然后就造成数据不准确了。
- 解决方法一、设置发送缓冲区成更大的值(不提倡)。
- 解决方法二、使用确认包,每次只发一个小包,客户端收到后向服务端发“确认”反馈,服务端等收到“完成”后再发下一个包。
- 解决方法三、采用完成端口技术……
所以我们要考虑大文件的时候,是否数据正常接收。这里,最好采用“确认机制”,或者是“文件分割编号机制”,文件分割方法个人感觉较好,在客户端可以方便组装!如果还是不能正常接收文件建议大家检查数据是否丢包(或者服务器线程简单的休眠(Sleep),调试程序)。
大文件传输结构体模型:
1、接下来思路是:服务器文件传输线程分块儿读取文件发包,然后封装成普通消息发给客户端。客户端接收来自服务器端的消息,判断是否是文件传输消息,如果是文件传输消息,直接交给客户端文件传输线程,最后判断id和last只需分块而写入文件即可!
2、理论上支持大文件传输,测试了200M以上的无压力,更大的文件的没有测试,BYTE data[1024],可以根据消息容纳字节数,自己调整buff缓冲区。
备注:TCP可能的丢包现象:
简单写了一个传输JPG图片的程序,图片但是只能显示一半,下半部分图片无法正常显示(花屏)!因为会发生阻塞,所以研究了好长时间,结果加上一个Sleep(300),服务器发过一次数据之后休眠,解决了此问题。
服务器端:
06 | sockSrvr.Accept(sockRecv); |
08 | tFile.Open(_T( "C:\\Cache.jpg" ), CFile::modeRead | CFile::typeBinary); |
09 | ULONGLONG myFileLength = tFile.GetLength(); |
10 | sockRecv.Send(&myFileLength, 8); |
12 | byte buff[1024]; int reVal; |
14 | int Count = myFileLength/1024+1; |
15 | if (myFileLength%1024==0) --Count; |
16 | for ( int i=0;i<Count;i++) |
18 | tFile.Seek(i*1024,CFile::begin); |
19 | reVal=tFile.Read(buff,1024); |
20 | sockRecv.Send(buff,reVal); |
客户端:
04 | sockClient.Connect(_T( "192.168.4.78" ), PORT); |
06 | sockClient.Receive(&dataLength, 8); |
09 | int Count = dataLength/1024+1; |
10 | if (dataLength%1024==0) --Count; |
11 | CFile tFile(_T( "C:\\Cache.jpg" ), CFile::modeCreate | CFile::modeWrite | CFile::typeBinary); |
12 | for ( int i=0;i<Count;i++) |
16 | sockClient.Receive(buff,dataLength-i*1024); |
17 | tFile.Seek(i*1024,CFile::begin); |
18 | tFile.Write(buff,dataLength-i*1024); |
22 | sockClient.Receive(buff,1024); |
23 | tFile.Seek(i*1024,CFile::begin); |
24 | tFile.Write(buff,1024); |