c# socket 传输文件

relive_7 2008-05-14 11:40:34
大家好,我是一名大四的学生。最近在做毕设,遇到了在c#中socket传输大文件的问题。
我的大体思路有两个(参考网上的资料)
----------------------
(1) 个人认为效率比较低
连接..
发送第一个字节块...
等待确认...(接收确认信息)
确认
发送第二个字节块...
等待确认...
确认
发送第三个.....
....
(2)个人认为效率比较高

发送端一直写入网络流
接收端一直读取网络流
----------------------
我在每个字节块的前面加入了一个int型的变量,它表示每次发送文件数据的长度
我根据思路(2)写了代码
如下
----------------------
接收端

private void Listener() //开始监听传输请求
{
IPHostEntry ipHostInfo =Dns.Resolve(System.Net.Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
this._ls =new TcpListener (ipAddress,6688);
this._ls .Start ();
while(true)
{
Socket socket=this._ls .AcceptSocket ();
this.txtConnect .Text =socket.RemoteEndPoint .ToString ();
Receive(socket); //调用接受文件函数
}
}
//我在每个字节块的前面加入了一个int型的变量,它表示每次发送文件数据的长度
private void Receive(Socket socket) //接受文件函数
{
NetworkStream ns = new NetworkStream(socket);
FileStream fs = new FileStream("c:\\file.txt", FileMode.OpenOrCreate);
bool isRead = true;
while (isRead)
{
int count = ns.Read(this._receiveBuf, 0, this._receiveBuf.Length);
int datanum = 0;
datanum = BitConverter.ToInt32(this._receiveBuf, 0);
if (datanum > 0) //如果传输的文件字节数>0 证明还有数据没有传输完
{
fs.Write(this._receiveBuf, 4, datanum);
fs.Flush();
}
else //datanum = 0 ,文件发送完毕
{
isRead = false;
}
}
this.txtFile.Text = "文件传输成功";
fs.Close();
}

----------------------
发送端

private void btSend_Click(object sender, System.EventArgs e) //点击按钮后开始传输
{
if (this._isConnect)
{
_ns = _tc.GetStream();
string path = this.txtPath.Text.Trim();
FileStream fs = new FileStream(path, FileMode.Open);
int sendCount = 0;
byte[] countbuffer = null;
byte[] clientbuffer = new byte[1004];
while (sendCount < fs.Length && _ns.CanWrite)
{
int count = fs.Read(_sendBuf, 0, _sendBuf.Length); //从文件中读出数据
countbuffer = BitConverter.GetBytes(count); //表示每次读出了多少字节数
countbuffer.CopyTo(clientbuffer,0); //将count加入数组首部
_sendBuf.CopyTo(clientbuffer, 4);
this._ns.Write(clientbuffer, 0, 4 + count); //写入网络流
sendCount += count;
}
countbuffer = BitConverter.GetBytes(0); //发送文件完后,读出字节数为0
this._ns.Write(countbuffer, 0, countbuffer.Length);
_ns.Close();
fs.Close();
}
}

----------------------
我发现有时能够成功,有时却陷入死循环,比如我传输2k的txt,结果很长时间都没有停止,我中断后发现生成了200M的txt
实在搞不懂是为什么,请大家帮我分析分析.


-------------------------------
关于思路(1)

我不会控制socket和相对应的networkstream
比如说发送端发送数据后,要等待接收端的确认信息
怎样让发送端停止发送数据来等待确认信息
接收到后又怎样重新发送数据
说简单一点就是发送端和接收端有序的操作网络流的问题
请大家多多指点
-----------------------------------
最后的问题:您觉得在socket上传输大文件时,如何能提高传输的效率?
networkstream的同步异步操作是怎么回事?能不能跟我说说他们的区别,最好来一个实例(beginread中的AsyncCallback asyncCallback到底是什么东西)

问了好多问题,可是我没有多少分给大家觉得很惭愧(等我有份了一定补给大家),但是我会衷心的谢谢大家
我的mail:6233843@gmail.com 如果有code的话您可以mail我
再一次谢谢大家
...全文
6793 42 打赏 收藏 转发到动态 举报
写回复
用AI写文章
42 条回复
切换为时间正序
请发表友善的回复…
发表回复
Hualalasummer 2012-08-14
  • 打赏
  • 举报
回复
学习了
xmvagrant 2011-11-28
  • 打赏
  • 举报
回复
现在也在学习socket,学习中
xbl002 2011-06-07
  • 打赏
  • 举报
回复
现在也在学习socket,学习中
ywh619662772 2010-12-11
  • 打赏
  • 举报
回复
socket编程协议学习很重要!
Tony_Z 2010-10-13
  • 打赏
  • 举报
回复
hhuke 2010-09-07
  • 打赏
  • 举报
回复
楼主sb,tcp是可靠的文件传输
ningbaolin 2010-06-12
  • 打赏
  • 举报
回复
正好我现在做一个网络编程程序设计,你的代码借着用哈了。
iverson545 2010-01-20
  • 打赏
  • 举报
回复
up up
iverson545 2010-01-20
  • 打赏
  • 举报
回复
顶,学习。。
lijia4 2009-12-06
  • 打赏
  • 举报
回复
不错嘛,Mark。
bluesky_001_001 2009-12-03
  • 打赏
  • 举报
回复
学习一下
fdg03fdd03 2009-08-18
  • 打赏
  • 举报
回复
谢谢!学习了
luofaming 2009-07-29
  • 打赏
  • 举报
回复
还要回复
yumn2004 2008-09-04
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 relive_7 的回复:]
请大家帮我看看
我写的接收端和发送端 有时候运行正确 有时接受端的文件会少很多数据(甚至发送两次就停止了)

接收端

C# code
/// <summary>
/// 将每次要发送文件的字节数放置在数据的首部
/// 服务器接收后将接收到的字节数发回
/// 发送端发送完成后接受服务器的发来的字节数
/// 然后与自己发送的字节数比较,进行检验
/// 发送文件完成后发送count=0的消息…
[/Quote]
今天仔细看了楼主的code,对这一句:
int count = fs.Read(_sendBuf, 0, _sendBuf.Length); //从文件中读出数据
很疑惑啊,楼主每次都是从文件流的开始位置读起数据,这样测试结果也对??似乎要用sendCount加以控制吧,请指教!
yumn2004 2008-08-28
  • 打赏
  • 举报
回复
好贴,学习了很多东西!!
ORSCAR 2008-05-16
  • 打赏
  • 举报
回复
LZ可以送10分技术分给我吗?急用`谢谢啦`好心有好报!
cc_net 2008-05-16
  • 打赏
  • 举报
回复
mark
fengyecsdn 2008-05-16
  • 打赏
  • 举报
回复
以上的算法可以根据需要变换。 比如你要传输的东西太大,接收和发送方都吧所有数据放内存里等待校验和重发是很浪费的。
那么你在发送前就该先吧数据分段。比如不分段需要1000个包,那么你可以线分成20段,每段50个包。每完成一段,就确认一下,吧数据写入磁盘,继续处理下一段。
不过如果要求传输的是命令队列(一般这东西要求及时处理,不能耽搁)那么你最好采用类似ATM的传输方式。接受一个,处理一个。
fengyecsdn 2008-05-16
  • 打赏
  • 举报
回复
http://topic.csdn.net/u/20080202/09/2a639488-5c1e-42d2-9d11-3f6e2ceebc26.html

楼主可以参考我的回帖。

另外,楼主如果不是必须自己写所有代码,我可以给你我的一个类库。封好了传输功能。

对算法嘛。楼主的想法几本是对的。但是没自己看你的代码质量。

C/S都开两个线,一读一写。每个包头上加序号, 3579/100/1 3579/100/2 3579/100/3以此类推
3579表示该数据块的编号。 100表示一共分了100个包,后便的数字表示当前是第几个包。
接受方把接到的数据包都保存下来,一旦发现数据不连续,就请求一下。比如3579/100/23 之后得到 3579/100/25
那么就再请求一下 3579/100/24, 发送方得到这个后,再把24包补发一次(包里要注明补发,以免接收方吧计数器弄错),
数据传输完成。接收方返回一个确认指令。传输完成。
relive_7 2008-05-16
  • 打赏
  • 举报
回复
感谢大家对我的帮助

有哪位大大给我推荐一些网络编程入门的书?
我突然很想系统的学习一下

再次感谢大家对我的帮助
加载更多回复(22)

110,534

社区成员

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

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

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