socket 文件传输优化问题 高手进来帮忙啊!周公看到请进!(200分)

cqsfd 2009-11-12 11:08:39
本人新手,只有几个月的实习经验,也不知道问的问题是不是比较白痴...跪求各位高手指点。两个问题200分,不需要修改我的程序,给我点明程序思想即可,另开一贴给100分

下面是我写的一个socket文件传输程序片段,总体思路是:
1:一个线程循环接收服务器发出的指令
2:当接收到传输文件的指令时,就把需传输的文件信息插入队列
3:同时生成一个新的传输文件类,该类work()方法启动一个新线程,从队列中提取文件信息进行相应文件的传输

具体代码如下
else if (sCommand == "GET_FILE")
{
.....

queue.Enqueue(Uuid + '|' + sPath); //queue队列是自己定义的线程同步的队列,同步问题不需要考虑
Send_filesClass cc = new Send_filesClass();
cc.work();

}

public class Send_filesClass
{
private TcpClient tcpc;
public Send_filesClass()
{
this.tcpc = new TcpClient(xxx, 9001);
}
public void work()
{
Thread t = new Thread(new ThreadStart(run));
t.IsBackground = true;
t.Start();
}
private void run()
{
NetworkStream nstream = tcpc.GetStream();

... //while循环:fFileStream文件流读文件,每次102字节,再用nstream发送出去

fFileStream.Close();
Thread.Sleep(500);
nstream.Close();
tcpc.Close();

}
}

现在的问题是:

1:每次同时传输2个文件,我打开本机cmd 输入netstat -a 查看9001端口,2个文件有时会有8个在打开的端口,其中的大部分状态是Time_Wait,为什么呢?是不是我程序中间的设计有问题?有人和我说过,Send_filesClass这个类中,需要用到的socket在构造时传入就好,用一个nstream获取其中的流;但是这个socket不是任何时候都需要,不是长连接的,用完就关掉,不好判断它什么时候被实例化好,所以我把socket放到类中。是不是这里有问题?还有就是这个类传输完文件后,何时被系统回收?我在程序中写的是每次传输完,线程sleep半秒后就关闭流,可是查看本机端口信息,基本都得等个10-20秒端口才释放出来,那这个类岂不是在内存中留得更久?如何在程序中手动释放资源?

2:传输效率非常低。
我用自己机器测试,把文件发送到服务器的同时,将其下载到本机。
刚开始下载时,和网上其他下载资源差不多,都是一上来速度达到疯狂的几百K,1-2秒后,基本都维持在20k左右,这是为什么?如何提高?
我有个想法,对Send_filesClass类中传输文件的方法进行修改:将文件流一段段的先读出来,插入一个队列,再从队列中取流发送出去;如果只用一个线程取流发送,是不是可以省去文件流读取的时间?相当与先将文件流读入内存再发送?
如果我将每段文件流编号,用N多的线程从队列取流出来发送,服务器端接收到再组装起来,传输效率能提高很多吗?


问题比较琐碎,希望高手们踊跃发言,很多和我一样的新手,都将感恩戴德
...全文
461 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
hitsunyboy 2011-10-26
  • 打赏
  • 举报
回复
楼主学习知识的热情让后来人钦佩 虽然帖子早就结贴了 但是还是想顶下
nzzb1985 2010-06-17
  • 打赏
  • 举报
回复
顶下!!!!
kingrain213 2010-05-25
  • 打赏
  • 举报
回复
我也在做Socket,也有好多不懂,方便留个QQ联系一下么?请多多关照,QQ :284069003
cqsfd 2009-11-12
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 qldsrx 的回复:]
那就再给你一个建议,C++、C#两个一起学,同时掌握多种编程语言也不是坏事,特别是到了.NET编程,最终都是解析到IL上的,所以C++、C#最终都是编译到IL代码在执行,你别说你不用.NET,返回以前的VC6.0,那样你没法写出适应新操作系统,比如WIN7运行的程序的。
[/Quote]
是的,我也是想今后主攻C++,但也不放弃C#
非常感谢各位的回帖,我另开一贴讨论,散分快点。只能发100分的帖子,还承诺了要给前面的兄弟分,在这里没分的兄弟别介意,到新帖补上。
qldsrx 2009-11-12
  • 打赏
  • 举报
回复
那就再给你一个建议,C++、C#两个一起学,同时掌握多种编程语言也不是坏事,特别是到了.NET编程,最终都是解析到IL上的,所以C++、C#最终都是编译到IL代码在执行,你别说你不用.NET,返回以前的VC6.0,那样你没法写出适应新操作系统,比如WIN7运行的程序的。
cqsfd 2009-11-12
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 qldsrx 的回复:]
引用 16 楼 cqsfd 的回复:
青龙白虎兄,我刚仔细看了你的代码,貌似都是直接用异步调用的啊!文件也是用socket.sendfile()
直接用C#封装好的方法,不易扩展啊。以后老板肯定要求我做多文件,多线程同时传输的,所以我才会使用文件分块的方法,而且以后我也想转行干VC了,C#太不好混了
你的这段代码先收藏着吧,非常感谢

socket.sendfile()其实就是偷了个懒,我也写过用文件流读取传输,不过不是用的那种方法了,是用XXXAsync系列方法,效率更高,但不适合初学者。

另外你说C#不好混,这想法不对,抱着混的态度怎么行,虽然有很多人抱怨C#这样那样不好的地方,难道VC++就好了吗?至少我认为C#还是非常棒的,因为它易学,而且语法非常棒,同JAVA,Go语法相近,同时也支持VC++的各种扩展,比如指针也是可以使用的,虽然不建议使用。如果研究到底层,C++能做的,C#也能够做到。如果高兴的话,你也可以在C#里面直接使用IL编程,以提高运算速度。由于很多人学C#只学个皮毛就得意忘形了,一旦遇到挫折就以为C#只能做到那么点程度,所以才会有很多人乱发牢骚,要转行。
[/Quote]

其实我一开始就打算用的XXXAsync系列,比较了下还是放弃了,原因上面已经提到了...这个C#确实做得很好,虽然现在没用到,我也正在研究这一块,委托啊什么的
你说的C#的优点确实也是对的,很多和我一样的C#初学者的困惑都是:
1-用C#开发windows桌面,进不了大公司,也许以后情况会改观,但当我明年毕业时,VC还是吃香的
2-C#易学,介绍C#怎么实现功能的讨论很多,但是讨论如何做得好的,真是太少太少了!前段时间周公大大发了一篇托管/非托管代码的帖子,是我学C#几个月来见过的真正介绍优化和C#背景知识的文章。还有sp1234,也能提很好的框架性的意见(现在很少见到了)。这方面的资料和vc比起来真的太少了!所以我开了这个帖子,希望高手们多多发言,但只引来了你们几个高手了。再搞C#下去,感觉自己完全就要成为一个代码工人了,实现功能的代码满天飞,是个人都能搞C#开发,不是要逼死做C#的程序员吗!
kennie_190602169 2009-11-12
  • 打赏
  • 举报
回复
帮顶
qldsrx 2009-11-12
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 cqsfd 的回复:]
青龙白虎兄,我刚仔细看了你的代码,貌似都是直接用异步调用的啊!文件也是用socket.sendfile()
直接用C#封装好的方法,不易扩展啊。以后老板肯定要求我做多文件,多线程同时传输的,所以我才会使用文件分块的方法,而且以后我也想转行干VC了,C#太不好混了
你的这段代码先收藏着吧,非常感谢
[/Quote]
socket.sendfile()其实就是偷了个懒,我也写过用文件流读取传输,不过不是用的那种方法了,是用XXXAsync系列方法,效率更高,但不适合初学者。

另外你说C#不好混,这想法不对,抱着混的态度怎么行,虽然有很多人抱怨C#这样那样不好的地方,难道VC++就好了吗?至少我认为C#还是非常棒的,因为它易学,而且语法非常棒,同JAVA,Go语法相近,同时也支持VC++的各种扩展,比如指针也是可以使用的,虽然不建议使用。如果研究到底层,C++能做的,C#也能够做到。如果高兴的话,你也可以在C#里面直接使用IL编程,以提高运算速度。由于很多人学C#只学个皮毛就得意忘形了,一旦遇到挫折就以为C#只能做到那么点程度,所以才会有很多人乱发牢骚,要转行。
cqsfd 2009-11-12
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 lybelmont 的回复:]
感觉 磁盘文件的读写 很浪费时间
减少磁盘操作的次数
一次性把文件读入内存 再处理会比较好吧
[/Quote]
是的,我也是这么想的,所以才有了先把文件所有快读入一个队列,再用N多线程从队列中取文件块的想法。
忘了说,我们的服务器是java写的,很多.NET的方法不能直接用的,必须得用底层的socket来通信
cqsfd 2009-11-12
  • 打赏
  • 举报
回复
青龙白虎兄,我刚仔细看了你的代码,貌似都是直接用异步调用的啊!文件也是用socket.sendfile()
直接用C#封装好的方法,不易扩展啊。以后老板肯定要求我做多文件,多线程同时传输的,所以我才会使用文件分块的方法,而且以后我也想转行干VC了,C#太不好混了
你的这段代码先收藏着吧,非常感谢
lybelmont 2009-11-12
  • 打赏
  • 举报
回复
感觉 磁盘文件的读写 很浪费时间
减少磁盘操作的次数
一次性把文件读入内存 再处理会比较好吧
cqsfd 2009-11-12
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 qldsrx 的回复:]
既然你说自己是新手了,那我也不给你过难的代码。我曾上传过简单的文件传输代码,适合新手看,效率当然要比你写的高,只不过不支持单个文件多线程,你多开几个客户端,可以实现多个文件同时下载(简单嘛):
C#实现简单的Socket文件传输示例
[/Quote]
非常感谢,代码待会好好研究下。
主要是希望大家说点概念上,框架性的东西,高手的经验之谈,难能可贵啊!
埋头苦干了一段时间,回过头来发现自己虽然会实现功能(大多从网上Ctrl+c的),但为什么这么做,怎么做更好就不知道了。真的不想以后成为代码民工!
qldsrx 2009-11-12
  • 打赏
  • 举报
回复
既然你说自己是新手了,那我也不给你过难的代码。我曾上传过简单的文件传输代码,适合新手看,效率当然要比你写的高,只不过不支持单个文件多线程,你多开几个客户端,可以实现多个文件同时下载(简单嘛):
C#实现简单的Socket文件传输示例
cqsfd 2009-11-12
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 leogle_reloaded 的回复:]
据我的印象,tcp中断连接后,会进入办关闭状态,防止对方没有收到ack,timewait是正常的
[/Quote]
这个我还是明白的,我的困惑是为什么程序只有2个链接,比如说服务器发了2个请求文件的命令过来,相应的我应该是生成2个传输文件类,每个类中1个链接,但是我打开本地端口的信息,发现我这边有8个端口于对方9001端口链接了,怎么会有这么多呢?我的理解是,2个链接只有2个端口啊

我的问题貌似太多太琐碎了,多加点分吧
感谢楼上几位兄弟的回帖,每人20分吧
问题都解决再拿出500分答谢大家,反正最近天天回帖也攒了不少分
cqsfd 2009-11-12
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 leogle_reloaded 的回复:]
你应该使用try catch finally来关闭socket
[/Quote]
异常到是没有的
刚开始我的程序中也到处是try catch finally这些,后来看网上高人评论说尽量设计好你的程序,尽量少用try,我就开始避免try的使用
请问try这种东西使用原则是什么?
cqsfd 2009-11-12
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 leogle_reloaded 的回复:]
楼主最近很活跃。
其实分割文件并不能提高速度,文件读入内存是需要时间的,最快的办法是使用内存映射,代码参考飞鸽传书,在我印象中应该是一个日本人写的
[/Quote]
最近不用赶项目,有时间上来转转,顺便发帖把自己一直搞不明白的框架性的东西提出来,这些需要高手的宝贵经验,自己看书老是搞不明白
我对文件传输的理解是:把本地硬盘上的文件上传,先得把文件块读入内存需要时间,每块需要时间a;然后发送出去,由于tcp的发送机制,每块需要时间b。我原来代码写的,是不是每次发送一块都需要时间a+b呢?发送10块不就是10(a+b)啦?所以就想在tcp发送等待确认的时候,先把文件都读入内存,这样发送10块只用a+10b,相当于省了文件读入内存的时间。这样的理解对吗?如果多开几个线程同时发送,是不是更快?
内存映射是什么东东?可否发个相关资料的链接?
leogle_reloaded 2009-11-12
  • 打赏
  • 举报
回复
据我的印象,tcp中断连接后,会进入办关闭状态,防止对方没有收到ack,timewait是正常的
leogle_reloaded 2009-11-12
  • 打赏
  • 举报
回复
你应该使用try catch finally来关闭socket
leogle_reloaded 2009-11-12
  • 打赏
  • 举报
回复
楼主最近很活跃。
其实分割文件并不能提高速度,文件读入内存是需要时间的,最快的办法是使用内存映射,代码参考飞鸽传书,在我印象中应该是一个日本人写的
cqsfd 2009-11-12
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 hhc123 的回复:]
Thread.Sleep(500); 这个要干什么的啊
[/Quote]

因为我的客户端用C# 服务器端用java
传输完文件马上close服务器端接收会有问题,所以让他sleep了一会
加载更多回复(5)

110,545

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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