文件传输功能库项目的开发教训

本文记录了一次TCP文件传输项目的开发过程,详细介绍了在遇到传输速率低及文件传输不完整等问题时的调试经历,总结了盲目调试的教训,并分享了正确的调试方法和技术要点。

这个项目的主要功能是搜索局域网内的另一台终端,然后尝试与其建立TCP连接,查看和操作其上的文件,上传和下载文件。

预期是一个星期内做完,但是结果花了三个星期。。。严重BS自己。

虽然说代码的总体是在一个星期内写完的,但是在传输文件的时候遇到了两个问题,一个是传输速率过低,另一个是文件传输不完整。为了解决这两个问题,花了两周的时间。但是调试的方法非常盲目,完全是没有效率的工作方式:

一开始考虑传输速度的问题是设置每次发送的单位是32KB,这是非常直观的做法,而这事实上可以改善性能。首先是减少了SOCKET的SEND和RECV的系统调用,原因并不只是这里,速度的瓶颈是读磁盘或者FLASH文件的操作非常耗时(相对于网络速度),而加大每次发送的单位,读的时候也读的比较多,减少了文件读的操作。所以在对程序性能进行优化的时候,应该每一步都要有非常确切的理由才去尝试。否则只是低效率的盲目操作。

对于性能瓶颈应该积极的想办法解决,通过查找资料,确定解决方案。关于文件读写,尤其是写时速度过慢,也没有很好的解决这个问题。

然而在这之前还有一个更愚蠢的错误。一开始的传输速度非常慢,只有100KB/S,即使是增大了发送单位,发送缓冲和接收缓冲也没有帮助。最后找到原因是在发送端的读-发循环和接收端的收-写循环里的结尾多了一句waitForShutDown(100)的等待语句,这样当然速度会慢。显然在写代码的时候不够专心,没有在写代码的时候确认每一句的意思。

只有确切的理由才去编写和优化代码——就是这么简单的原则。没有遵守的原因就是心态问题:不够认真耐心,没有写出优秀的软件的意愿。对自己的要求有点太低了。The code works, that's Everything!

而关于传输比较大的文件不完整的问题,一开始就认为是文件尾部的数据没有能够发送过来导致的,所以认为是发送端过早关闭了连接,于是就设置了SOCKET的SOLINGER选项,但是没有起到作用。这时候应该分析原因到底是不是文件尾部的数据没有发送过来,而不是盲目的反复修改发送和接收缓冲试验。最后找到原因是recv函数的工作方式理解错了,并不是除非对方关闭SOCKET,否则阻塞,直到读满len指示的长度,而是目前有多少数据都尽可能取出,所以每次recv返回的时候,数据大小都不一定是对方send的时候的单位长度(不然为什么要有整型返回值?)。

当程序出现不知道原因的问题的时候,应该做的是尽可能的列出可能的原因,但是可能不会想到原因。而工程实践的方法是使用DUMP,将每一步的结果都输出来检查错误的地方。一开始如果将每一次发送和接收的大小都输出检查就可以马上找到这个错误。

态度和方法不对导致这一次的教训,心情被搞得很糟糕。

不过这次也充分反应了自己的知识储备完全不够!虽然一开始有时间去准备资料,但是时间比较短,如果之前没用过某方面的知识,就可能在使用的时候出错(不过对recv的行为实在是太主观认定了!)。

另外的问题就是一开始应该找现成的库或者组件,假使没有合适的,也可以借鉴类似功能的。不看看别人怎么做的,又请问怎么能够提高自己的水平呢?

闭门造车。固步自封。

PS:另外的问题是在MFC里使用了wstring,而不是与环境有关的CString来编写程序,造成了和界面使用的某个库的字节环境部一致的问题。

 

国有乐,民自贤。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值