QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2035|回复: 12

有用TCP套接字传送文件经验的朋友请进来看看

[复制链接]
发表于 2004-8-3 01:49:19 | 显示全部楼层 |阅读模式
小弟正在做的软件中的一部分涉及到直接使用TCP套接字传送文件,有点疑问的地方

详细请点击下面查看(不要注册)
http://www.loveunix.net/index.php?showtopic=35835

因为我在那里不止发了一个贴,而且还有其他人的意见,所以直接贴地址了,还请高手麻烦点击一下去看看。


我想有经验的可以一起讨论讨论或者赐教。

劝我用FTP来传文件的话就不必了
发表于 2004-8-3 10:29:53 | 显示全部楼层
你最后的问题在哪里。我是不喜欢看长贴的啦(灌水除外)。
回复

使用道具 举报

 楼主| 发表于 2004-8-3 13:05:25 | 显示全部楼层
哈,我发现一个奇怪的现象

我原来的代码中,客户端接收一个数据块之后是不发送应答信息的,也就是说服务器拼命传,直到文件结束。OK,在我用来测试的几个文件中,有几百字节的,有5M的,有11M的,还有个130M的。

我之前定义的File Block是如下的:

struct FBLOCK {
   int  info;
   int  bsize;
   char  data[1000];
};

其中不是有个info量么,可以用来存放一些标志信息,我用来放了表示文件结束的信息,发送方在跳出发送文件循环后会把info的值置为表示发送完的某个值,然后发送给接收方。因为我发现接收方在read()时不能保证在文件接收完全后正常退出,所以使用这样的标志信息,虽然接收方每次要判断一下,但是保证了正常退出。

问题来了,如果完全按照我上面提供的两个函数来进行文件传送,那么在传送11M文件的时候会导致在某个时候info变量的值出现了非预期的情况,从而中断了传输。而在传送130M的文件的时候,在最后一个包的地方也会出错,info变量的值也很奇怪,所以得到的文件要比原文件小点。并且还不能连续使用传送命令,原因同样是info的问题。

可是,如果我在函数中加点语句,例如计算发送的包数据(在循环中 count++),再显示出来;或者是接收方每次收到一个包后发送一个应答信息,发送方每次发送一个数据后等待接收这个应答信息。那么,一切OK!没有问题,连续使用传送文件命令也没有问题,info变量的值也不会很奇怪。

-------------------
以上的情况我试验了好几次了,希望有人能用我提供的函数自己试一下。我不知道是不是特殊情况。

就其原因,我胡乱猜测,由于我是本地到本地的传送,速度很快,而加了应答信息或者count++语句后发送发发送的频率没有那么快,也就不会出错了??

真的是好奇怪的现象,
回复

使用道具 举报

 楼主| 发表于 2004-8-3 13:05:45 | 显示全部楼层
经过修改函数,添加了应答信息后,真的是一切正常。。。。

本地并发处理没有问题,我同时传送两个不同的130M的文件,或者传送同一个文件的两份拷贝,都没有问题。

粗看起来一切正常,但是我还是想究其原因。。。

难道真的需要控制传送的频率吗???
回复

使用道具 举报

发表于 2004-8-3 14:11:14 | 显示全部楼层
[quote:08553d0da1="ImHow"]

难道真的需要控制传送的频率吗???[/quote]

是的,如果你传送的频率超过了服务器(或客户)端所能承受的最大限度,服务器(或客户)端就会忽略你的请求。为了检验,你可以用一个请求发送时间间隔呈扫描分布的客户端来检验服务器端的最大响应能力。

具体步骤是:先确定一个足够大的发送请求的时间间隔(IAT),然后在客户程序中逐渐减小IAT,直到服务器不能对客户的请求进行及时响应,这样就可以得到最好的请求发送频率。
回复

使用道具 举报

 楼主| 发表于 2004-8-3 14:25:00 | 显示全部楼层
“直到服务器不能对客户的请求进行及时响应”

怎么判断?我现在的解决方法是在接收方添加一个发送应答信号,在发送方接收一个应答信号,然后再发送下一个数据包。
回复

使用道具 举报

发表于 2004-8-3 15:45:01 | 显示全部楼层
可以采用向标准输出来输出数据的方法
回复

使用道具 举报

 楼主| 发表于 2004-8-3 16:53:20 | 显示全部楼层
我添加应答信号也是为了延迟,发送方不收到接收方发过来的应答信号是不会发送下个数据包的

不过估计还要添加超时处理,虽然我设定了信号函数,但是要是网络断掉就没辄了,呵呵
回复

使用道具 举报

发表于 2004-8-3 19:12:13 | 显示全部楼层
超时处理相对来说没那么重要,但作为完善程序的一个步骤当然是必不可少的。
你说的“应答信号”会降低程序执行效率。所以我认为还是找出最优的发送时间间隔是最佳解决方案。
回复

使用道具 举报

 楼主| 发表于 2004-8-3 19:30:18 | 显示全部楼层
我也知道每次接收并且判断肯定会降低效率。目前只是一个延缓之计

因为我对如何准确的计算发送间隔,如何延迟还没有什么头绪

看起来你有这方面的经验,不知道能不能点拨点拨,不胜感激 :-)
回复

使用道具 举报

发表于 2004-8-3 20:21:52 | 显示全部楼层
具体步骤嘛,你可以这样来实施……
看下面这点代码:
double ht = 0.25L, it = 0.001, dt, iat;
int ii, steps = 100;
dt = (ht - lt) / (double) steps;
for (ii = 0; ii < steps; ii++) {
    iat = ht - ((double)steps * dt);
}

ht是你指定的最大的间隔时间,lt是最小的间隔时间,你要从最大的过渡到最小的。steps表示dt递减100次减到lt. iat是发送的时间间隔(当然如里你要尽可能精确的iat的话可以增大steps的值)。
就使用类似的代码来控制时间间隔。

所以说你可以在发送请求前计下当前时间bef,发送后计下当前时间aft。前后时间之差(aft-bef)就是你发送请求所用的时间。再用你计算出来的iat-(aft-bef)就是你的程序需要休息的时间,用sleep就可以了。

不断地循环……循环……最后就有你要的东西了,哈哈
回复

使用道具 举报

 楼主| 发表于 2004-8-3 21:06:35 | 显示全部楼层
那个循环有什么用吗。。。。iat的值又不变的啊

是不是应该是:
[code:1]
for (ii = 0; ii < steps; ii++) {
        iat = ht - ((double)ii * dt);
}
[/code:1]

那就是在客户端和服务端建立连接后就计算一下这个值保存起来喽~我考虑考虑~~
回复

使用道具 举报

发表于 2004-8-3 21:16:29 | 显示全部楼层
嗯,是的,打错了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-7 18:13 , Processed in 0.046384 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表