原帖链接http://topic.csdn.net/u/20091112/11/54935b2f-b2b8-4d58-af30-40379860e581.html
回帖中还有几个小问题,一并帮着看看吧
本人新手,只有几个月的实习经验,也不知道问的问题是不是比较白痴...跪求各位高手指点。两个问题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多的线程从队列取流出来发送,服务器端接收到再组装起来,传输效率能提高很多吗?
问题比较琐碎,希望高手们踊跃发言,很多和我一样的新手,都将感恩戴德
回帖中还有几个小问题,一并帮着看看吧
本人新手,只有几个月的实习经验,也不知道问的问题是不是比较白痴...跪求各位高手指点。两个问题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多的线程从队列取流出来发送,服务器端接收到再组装起来,传输效率能提高很多吗?
问题比较琐碎,希望高手们踊跃发言,很多和我一样的新手,都将感恩戴德
如果你用NetworkStream,就是打算不考虑效率了,因为NetworkStream没有效率可言,它只是为了让网络传输看起来像是个流才存在的,不建议考虑效率的人使用,应该使用Socket。至于端口占用,客户端每打开一个Socket连接,就会占用本地一个端口,何时占用端口就要看协议类型了,要关闭端口只要调用Socket的Close方法,即可释放所有资源,但是资源的最终回收是靠GC来回收的。对于文件上传下载,如果能够重用内存资源,做到可以一次性分配内存,不重新获取内存,速度才是最佳的。当我们序列化一个类到字节数组,或者从文件流读取到字节数组,程序就会向操作系统申请内存空间来存放这些内容。如果只申请不释放,那么内存占用就会越来越多,这不是我们想看到的结果。但是如果频繁地释放-申请内存,不但造成内存碎片,还占用了CPU时间,大大影响了效率。XXXAsync就是可以重用内存的高效传输方式,但使用起来难度也是相当高的,如果使用者内存预分配不当,也会造成不好的影响。
青龙白虎兄又来帮忙顶贴了,非常感谢!
我贴出的这段代码用的是tcp,我在其他地方用的是socket...在我的程序中,这两个是混用的,因为之前我一直不知道二者有什么区别...这就是代码工人的悲哀啊!要不再给我讲讲这二者的区别吧!我提到的将文件块插入队列,同时开新线程从队列取文件块发送应该比一次性分配内存,再从内存中发送更好,因为我只读入一块的时候就开始发送了,读入其他块是在socket发送等待对方接收确认这段时间完成的。就拿前一个帖子的例子,如果要传输的文件分为10个块,每个块读入内存需要时间a,传输出去需要时间b,如果一次都读入内存再发送,需要时间还是10a+10b,而插入队列貌似可以是a+10b。我理解的对吧?不过最好的方法应该是上个帖子有高人提到的用内存映射的方法,刚才查了下,相当于省了文件读入内存的时间,以后有空得好好研究下!我很奇怪的是,为什么我程序里,要发送2个文件时,明明是产生2个类,启用2个链接,在我的印象里,应该在本机只有2个端口与服务器链接啊,为什么我打开端口查看的时候,发现有8个端口链接呢?是我这边程序问题还是服务器那边设定的问题?
而且我想做到手动释放资源,等GC来释放太慢了,以后也想在其他方面也尽量手动释放资源,这点希望周公前辈来解答。
个人经验,文件不要多个同时传,要以一个文件为整体的一个一个传递,
在传递一个文件的时候,可以通过算法将文件切分开,然后再用相对数量的线程同时发送,
接收方将收到的东西组装好,这样可以大大的提高传输的效率问题。关于第一个问题,还没遇到过,关注
刚才把NetworkStream.write改成socket.send了,速度提高了1倍多近两倍!各位还在用NetworkStream.write传输数据的可以考虑修改一下!
我提到的队列,是想做出多文件,多线程同时传输,想BT,迅雷那样,当然功能没他们那么强大。现在听大家的意见,貌似这个方法不太好,我研究下内存映射再修改吧。
然后我的代码都贴出来了,省略掉的地方大家也一看就懂,为什么出现8个端口的奇怪现象不懂,难道tcp本身就可以这样?
用多线程传输和接收处理好了可以增加速度,但是如果处理不好,或许速度不升反降。