讨论:关于用winsock进行文件传输的两个小问题

happy_sea 2008-07-28 10:42:16
我现在正在把自己写的一个文件传输的代码封装为类,有两个小问题跟大家请教和讨论一下:
1、大家都知道winsock的缓冲区大小是8K,大文件需要分包发送,那么这个包的大小设为多少比较合适呢?我参考了几个文件传输的代码,有的设置为1K多,有的4K多,有的甚至是64K。据说IE的数据包大小是1045字节,因为这个大小最不容易引起网络阻塞,不知道这是不是真的?按我的理解,应该综合考虑联网方式、网速快慢、CPU处理能力等因素来决定这个包的大小。我以前的包的大小是8192字节,也就是正好是缓冲区的大小,在本机上或局域网中测试正常,外网间传输时有时会中途卡死,没有查到别的原因,是不是数据包的大小不合适造成了阻塞?
2、我的发送部分关键代码如下:
    If m_lFileSize <= TRUNK_MAX_SIZE Then           '如果要发送的文件小于数据块大小,直接发送
ReDim bData(1 To m_lFileSize) '根据文件长度重新定义数组大小
Get #nFileNum, , bData '读取数据
Close #nFileNum '关闭文件
wskData.SendData bData: DoEvents '发送数据
GoTo SendFinished
End If

'文件大于数据块大小,进行分块发送,直到剩余<=TRUNK_MAX_SIZE的最后一块
Do Until (m_iPos >= (m_lFileSize - TRUNK_MAX_SIZE)) '发送整块数据的循环
ReDim bData(1 To TRUNK_MAX_SIZE) '定义数组用于存放数据
Get #nFileNum, m_iPos + 1, bData '读取数据
wskData.SendData bData: DoEvents '发送数据
'RaiseEvent SendedSizeChanged(m_iPos) '触发SendedSizeChanged事件
m_iPos = m_iPos + TRUNK_MAX_SIZE '移动iPos,使它指向下次要读的数据
Loop

'发送最后一块
ReDim bData(1 To m_lFileSize - m_iPos) '定义数组
Get #nFileNum, m_iPos + 1, bData '读取数据
wskData.SendData bData: DoEvents '发送数据


接收部分关键代码如下:
Private Sub wskData_DataArrival(ByVal bytesTotal As Long)
Dim bData() As Byte
Dim nFileNum
nFileNum = FreeFile
Open m_sLocalFile For Binary As #nFileNum '打开文件准备写入数据
m_lReceivedSize = LOF(nFileNum) '获取已保存文件大小
RaiseEvent ReceivedSizeChanged(m_lReceivedSize + bytesTotal) '触发ReceivedSizeChanged事件
ReDim bytData(1 To bytesTotal)
wskData.GetData bData '获取数据
Put #nFileNum, m_lReceivedSize + 1, bData
Close #nFileNum '每次写入后都关闭文件
If m_lReceivedSize + bytesTotal = m_lFileSize Then '如果当前文件已接收完成
m_bReceivedOK = True
End If
End Sub

以上代码请大家看看有没有不合适的地方?特别是接收部分,每次接到数据包都进行保存与先用copymemory放到一个数组等到全部接收完毕再保存效率相差大不大?
...全文
452 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
苏门答腊 2009-07-17
  • 打赏
  • 举报
回复
其实文件接收方,可以完全不用API就实现任意大小的缓冲区机制的。
嗷嗷叫的老马 2008-07-29
  • 打赏
  • 举报
回复
看这里,弄了一个,不需要自己管理封包以及发送过程的偷懒方案:)

http://topic.csdn.net/u/20080729/17/ce04c7d4-6b52-4938-b065-3c5be5d1b86e.html
僵哥 2008-07-28
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 _l_ 的回复:]
引用 7 楼 unsigned 的回复:
引用 1 楼 _l_ 的回复:
我传文件的时候 喜欢先吧文件转换成BASE64编码 写代码省事

完全是误导。文件转换为BASE64编码,先不说消耗,本身就多了两个转换过程,写代码又如何来省事?


你写代码不省事情 对我来说是省事情
都是现成的模块 无非就是多几行代码而已
你又不是我 怎么知道是误导呢?

不仅传文件发MAIL 我用 BASE64
再ASP中 我还有TEXT的字段来保存图片呢
[/Quote]
难道不用Base64就没有现成的代码?用Text字段保存图片,跟把所有传输都转为Base64两者有什么关联关系吗?完全就是一种对用户不负责任的态度。
_l_ 2008-07-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 unsigned 的回复:]
引用 1 楼 _l_ 的回复:
我传文件的时候 喜欢先吧文件转换成BASE64编码 写代码省事

完全是误导。文件转换为BASE64编码,先不说消耗,本身就多了两个转换过程,写代码又如何来省事?
[/Quote]

你写代码不省事情 对我来说是省事情
都是现成的模块 无非就是多几行代码而已
你又不是我 怎么知道是误导呢?

不仅传文件发MAIL 我用 BASE64
再ASP中 我还有TEXT的字段来保存图片呢

_l_ 2008-07-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 unsigned 的回复:]
引用 1 楼 _l_ 的回复:
我传文件的时候 喜欢先吧文件转换成BASE64编码 写代码省事

完全是误导。文件转换为BASE64编码,先不说消耗,本身就多了两个转换过程,写代码又如何来省事?
[/Quote]

你写代码不省事情 对我来说是省事情
都是现成的模块 无非就是多几行代码而已
你又不是我 怎么知道是误导呢?

不仅传文件发MAIL 我用 BASE64
再ASP中 我还有TEXT的字段来保存图片呢

僵哥 2008-07-28
  • 打赏
  • 举报
回复
之所以需要转换为BASE64编码,本身是有原因的,在早期的传输设备当中,由于需要一位奇偶检验位,所以只有7位有效数据位(缘由是早期只考虑ASCII编码的传输),所以才需要将复杂的数据编码转换为Base64进行传输。而目前这些设备并没有被完全淘汰掉,所以为考虑兼容性,部分网络协议,比如Email等仍然延用该编码。
僵哥 2008-07-28
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 _l_ 的回复:]
我传文件的时候 喜欢先吧文件转换成BASE64编码 写代码省事
[/Quote]
完全是误导。文件转换为BASE64编码,先不说消耗,本身就多了两个转换过程,写代码又如何来省事?
僵哥 2008-07-28
  • 打赏
  • 举报
回复
其实对于缓冲区大小的设置,在允许的情况下是越大越好,只是对于多连接的情况下可能对核心内存有一定的压力。至于考虑大小,这个通常只有设置一个TCP初始滑动窗口大小(Window Size),或者MTU时才需要考虑这些问题。而设置滑动窗口的大小,主要目的是使得TCP传输过程当中尽量减少窗口的改动,以提升效率。而设置MTU值,则是为了防止在MTU小的中间设备减小拆分包的次数,或者防止拆分包,从而提升效率。

所有这一些都不是应用层所需要考虑的问题。
僵哥 2008-07-28
  • 打赏
  • 举报
回复
1.缓冲区的大小,最合适的大小依链路决定,这个跟TCP的滑动窗口以及中间设备的MTU有关,默认情况下推荐使用8k,对于一些路由复杂的链路考虑到中间设备的MTU限制,最好是小于1500,而对于局域网可以使用64k,但是这个只是一个最大化的值,实际上还需要依据通讯双方机器的设置来决定.
2.发送的时候分包自由通讯层去分,在应用层代码只需要一次性调用SendData,除非数据不全部都在内存当中,比如发送文件,则可以读一部分发一部分。
happy_sea 2008-07-28
  • 打赏
  • 举报
回复
谢谢楼上的朋友,我主要是想把这个C/S方式进行文件互传的代码封装一下以后用着方便,所以不考虑web server或者ftp方式。

这是个讨论帖,就算朋友们说的不能解决我的问题,也非常欢迎!欢迎大家继续关注和参与!
_l_ 2008-07-28
  • 打赏
  • 举报
回复
要是本地网络 数据量大一点无所谓

远程网络 ,我一般只用来传递一些小文件

要真有大文件 我就考虑用 WEB SERVER 或者FTP了 别人现成的东西 可靠性比自己临时写的好多了
happy_sea 2008-07-28
  • 打赏
  • 举报
回复
但是那样会增大传输的数据量哦
_l_ 2008-07-28
  • 打赏
  • 举报
回复
我传文件的时候 喜欢先吧文件转换成BASE64编码 写代码省事
嗷嗷叫的老马 2008-07-28
  • 打赏
  • 举报
回复
这几天抽时间写个试试看
嗷嗷叫的老马 2008-07-28
  • 打赏
  • 举报
回复
[Quote=引用楼主 happy_sea 的帖子:]
我现在正在把自己写的一个文件传输的代码封装为类,有两个小问题跟大家请教和讨论一下:
1、大家都知道winsock的缓冲区大小是8K,大文件需要分包发送,那么这个包的大小设为多少比较合适呢?我参考了几个文件传输的代码,有的设置为1K多,有的4K多,有的甚至是64K。据说IE的数据包大小是1045字节,因为这个大小最不容易引起网络阻塞,不知道这是不是真的?按我的理解,应该综合考虑联网方式、网速快慢、CPU处理能力等因素来决定…
[/Quote]

网络方面玩得比较少.....

不过我在想,WINSOCK控件应该已经包办了封包的拆分与合并了吧....
dmgywan 2008-07-28
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 unsigned 的回复:]
To _l_ ,我错了,咱握握手,就此打止吧。
[/Quote]
还是僵哥的学识气量高 ~~
dmgywan 2008-07-28
  • 打赏
  • 举报
回复
-
xp_79 2008-07-28
  • 打赏
  • 举报
回复
帮顶!
happy_sea 2008-07-28
  • 打赏
  • 举报
回复
哦,对,是我说反了,哈哈。

我准备结贴了。

_l_、僵哥,谢谢两位热心回复我的问题,但是你们如果因为我的帖子闹得不愉快的话,我会觉得非常过意不去的。

在我结贴之前,希望两位已经握手言和,再次谢谢两位!
僵哥 2008-07-28
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 happy_sea 的回复:]
引用 21 楼 unsigned 的回复:
换句话说,如果楼主的问题是放置于UDP协议,那么这些都是非常必要的。


因为使用UDP协议的话,小于MTU的限制会造成包的重新拆分,从而使丢包率增大,而TCP是不会丢包的所以可以不考虑这个问题,是这个意思吗?
[/Quote]
是大于MTU的情况下可能会导致收到的数据不全或者提升丢包率。TCP协议自有协议层帮你处理这个问题。
加载更多回复(15)

1,502

社区成员

发帖
与我相关
我的任务
社区描述
VB 网络编程
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧