C#开发网络编程-应用层协议的选择问题?

cranebupt 2012-04-04 08:50:30
一直有个疑问想不通,请教下:
实现网络文件传输(上传或者下载),已知FTP可以完成,但是FTP是基于TCP实现的,想找一个基于UDP开发的方法实现文件传输,不知如何实现?或者不用应用层协议,仅基于UDP实现传输,但又不知道文件如何拆分(便于传输)?

谢谢了
...全文
231 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
myazrael 2012-04-05
  • 打赏
  • 举报
回复
HttpRequest不好吗?
cranebupt 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

如果要用UDP(比如NAT穿透的情况下),就要定义好传输协议,并实现重传机制。

比如,你可以定义这么一个包头(总共16个字节):
C# code

public partial class FileTransferHeader
{
public short MagicNumber = 0x5446; // 'FT' 特殊标记
public PacketType P……
[/Quote]

想法不错! 感觉从难易度和效果上来看 不如FTP 谢谢分享
cranebupt 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

UDP无连接,不可靠,用来传文件不大靠谱吧
[/Quote]

QQ软件实现的文件传输 我在网上看是基于UDP实现的。。。HOW?
cranebupt 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

服务器
C# code

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

class UDPServer
{
private Socket……
[/Quote]

谢谢分享!
gomoku 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]
……
NAT 没穿透怎么办?
[/Quote]
另案处理,或移送有关部门:)
he110w0rld 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

如果要用UDP(比如NAT穿透的情况下),就要定义好传输协议,并实现重传机制。

比如,你可以定义这么一个包头(总共16个字节):
C# code

public partial class FileTransferHeader
{
public short MagicNumber = 0x5446; // 'FT' 特殊标记
public PacketType P……
[/Quote]

NAT 没穿透怎么办?
gomoku 2012-04-05
  • 打赏
  • 举报
回复
如果要用UDP(比如NAT穿透的情况下),就要定义好传输协议,并实现重传机制。

比如,你可以定义这么一个包头(总共16个字节):

public partial class FileTransferHeader
{
public short MagicNumber = 0x5446; // 'FT' 特殊标记
public PacketType PacketType; // 类型
public uint RequestId; // 会话编号 (每个下载分配一个独特编号)
public uint PacketId; // 数据包编号
public uint Length; // 数据长度
}

public enum PacketType : short
{
Error = 0,
ReqDownload = 1,
AckDownload = 2,

ReqPackets = 3,
AckPackets = 4,

Data = 5,
Text = 6,
}


当客户端发出下载请求的时候,服务端可以进行准备,并告诉客户总共会有几个包,并给当前下载一个独特编号。

// 客户-要求下载文件
// 0 1 2 3
//-----------------------
// 1) 'F' 'T' 1 0 类型: 要求下载文件
// 2) 0 0 0 0 会话编号: (不使用)
// 3) 0 0 0 0 包块编号: (不使用)
// 4) 9 0 0 0 长度: 9
//--------------------------------------------------
// 5) 'h' 'e' 'l' 'l' UTF8文件名: hello.txt
// 6) 'o' '.' 't' 'x'
// 7) 't'

// 服务-通知下载就绪
// 0 1 2 3
//-----------------------
// 1) 'F' 'T' 2 0 类型: 传送文件就绪
// 2) 01 F2 31 1D 会话编号: 0x1D31F201
// 3) FE 0 0 0 包块编号: 总共会有254个包
// 4) 14 0 0 0 长度: 4*4 + 9
//--------------------------------------------------
// 5) .. .. .. .. MD5: 16个字节,用来最后判断文件是否完好
// 6) .. .. .. ..
// 7) .. .. .. ..
// 8) .. .. .. ..
// 9) 'h' 'e' 'l' 'l' UTF8文件名: hello.txt
//10) 'o' '.' 't' 'x'
//11) 't'


客户准备好接收文件磁盘空间后(比如假定每个包的数据为512个字节,只有最后一个包可以小于512),开始请求下载多个数据包,比如要求数据包[0,1,2]。

客户在收到一些数据包后,填入磁盘,并进行勾销。超过一定时间,还没有收到的包,比如包1,必须再次加入请求,比如如[1,3,4,5]。

// 客户-要求下载包块
// 0 1 2 3
//-----------------------
// 1) 'F' 'T' 3 0 类型: 要求传送(多个)数据块
// 2) 01 F2 31 1D 会话编号: 0x1D31F201
// 3) 0 0 0 0 包块编号: (不使用)
// 4) C 0 0 0 长度: 3*4
//--------------------------------------------------
// 5) 0 0 0 0 包块编号: 0
// 6) 1 0 0 0 包块编号: 1
// 7) 2 0 0 0 包块编号: 2

// 服务-发送包块
// 0 1 2 3
//-----------------------
// 1) 'F' 'T' 5 0 类型: 传送一个数据块
// 2) 01 F2 31 1D 会话编号: 0x1D31F201
// 3) 1 0 0 0 包块编号: 1
// 4) 0 2 0 0 长度: 512
//--------------------------------------------------
// ... 数据: 512个字节


当客户收到所有的包,进行完整性校验,可以通知服务器下载完毕。
这时服务端则可以结束当前下载会话。当然,如果服务端发现客户端一段时间没有请求,也可以结束会话。


cranebupt 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]

HttpRequest不好吗?
[/Quote]

WINFORM下实现。。。HttpRequest能用么?
stonespace 2012-04-05
  • 打赏
  • 举报
回复
UDP包不一定能发送接收成功,不可靠,如果要udp来实现文件传输,你必须写程序来判断哪个部分传输没有成功,然后重新传输,会比TCP的实现复杂得多,不是一个简单的程序,
  • 打赏
  • 举报
回复
UDP无连接,不可靠,用来传文件不大靠谱吧
orochiheart 2012-04-04
  • 打赏
  • 举报
回复
客户端

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;

public class UDPClient
{
private byte[] buffer = new byte[512];
private Socket client;
private IPAddress address;
private IPEndPoint endPoint;
private int port = 5690;
private string host = "127.0.0.1";

public UDPClient()
{
address = IPAddress.Parse(host);
endPoint = new IPEndPoint(address, port);
client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
}

public UDPClient(String host, int port)
{
this.host = host;
this.port = port;
address = IPAddress.Parse(host);
endPoint = new IPEndPoint(address, port);
client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
}

public int send(string text)
{
Console.WriteLine("向服务器发送的内容为:{0}", text);
int result = 0;
if (String.IsNullOrEmpty(text))
{
return 0;
}

buffer = Encoding.ASCII.GetBytes(text);
long start = DateTime.Now.ToBinary();
result = client.SendTo(buffer, text.Length, SocketFlags.None, endPoint);
if (result > 0)
{
Console.WriteLine("数据发送成功!!");
long end = DateTime.Now.ToBinary();
Console.WriteLine("耗时:{0}毫秒",(end-start));
}
else
{
Console.WriteLine("数据发送失败!!");
}
return result;
}

public void exit()
{
if (client != null)
{
client.Close();
}
}

public static void Main(string[] args){
UDPClient client=new UDPClient("121.28.233.213",5690);
client.send("001118631172868");
client.exit();
}

}

orochiheart 2012-04-04
  • 打赏
  • 举报
回复
服务器

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

class UDPServer
{
private Socket server;
// private byte[] buf;
private IPAddress address;
private IPEndPoint endPoint;
//private IPHostEntry hostEntry;
private ASCIIEncoding encoding = new ASCIIEncoding();

public UDPServer()
{
server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//hostEntry = Dns.GetHostName();
//address = hostEntry.AddressList[0];
////address = IPAddress.Parse("127.0.0.1");
////endPoint = new IPEndPoint(address, 5690);

address = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
Console.WriteLine(address.ToString());
endPoint = new IPEndPoint(address, 5690);
server.Bind(endPoint);
ThreadProcessor processor = new ThreadProcessor(server);
Thread thread = new Thread(new ThreadStart(processor.run));
thread.Start();
}

public UDPServer(string host,int point){
server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
address = IPAddress.Parse(host);
endPoint = new IPEndPoint(address, 5690);
server.Bind(endPoint);
ThreadProcessor processor = new ThreadProcessor(server);
Thread thread = new Thread(new ThreadStart(processor.run));
thread.Start();
}

private class ThreadProcessor
{
private Socket server;
private byte[] buffer = new byte[512];
public ThreadProcessor(Socket server)
{
this.server = server;
}

public void run()
{
while (true)
{
// IPEndPoint sender = new IPEndPoint(IPAddress.Any,0);
// EndPoint remote = (EndPoint) sender;

// int dataLen = server.ReceiveFrom(buffer,ref remote);
int dataLen = server.Receive(buffer);
if (dataLen > 0)
{
DateTime date = DateTime.Now;
Console.WriteLine("-------------{0}----------------",date.ToString());
Console.WriteLine("接收到的内容为:[{0}]",Encoding.ASCII.GetString(buffer,0,dataLen));
Console.WriteLine();
}
}
}
}
public static void Main(string[] args){
UDPServer server = new UDPServer();
}
}

orochiheart 2012-04-04
  • 打赏
  • 举报
回复
我只做过UDP的数据传输小练习 贴出来分享一下

111,126

社区成员

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

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

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