谁有UDP可靠传输文件的代码?

HYWServer 2005-09-12 03:13:57
200酬谢!
...全文
512 点赞 收藏 20
写回复
20 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
sct 2005-11-01
mark
回复
HYWServer 2005-09-21
你说的程序就简单的发送和接收,根本没做任何丢包处理。
回复
balloy 2005-09-21
由于牵扯到的文件实在太多,不可能全给你,你就先看看把,看看原理应该是没问题了。有什么不明白的,或者发现设计不合理的,欢迎讨论啊
回复
HYWServer 2005-09-21
先谢
回复
balloy 2005-09-21
RUDPSocket.cpp

#include "stdafx.h"
#include <Easiware/RUDP/MFC/RUDPSocket.h>
#include <Easiware/Win32/SystemEx.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

namespace Easiware{

namespace RUDP
{
namespace MFC
{
void CRUDPSocket::CreateSocket(unsigned short nPort)
{
if (!CSocket::Create(nPort, SOCK_DGRAM))
{
throw Net::CSocketException(_T("无法创建Socket!"));
}
}

CRUDPSocket::ReceivedData CRUDPSocket::SendPacket(const void* pBuf, int nBufLen, const sockaddr_in& saTarget, uint32 nAck, uint16 nFlags, bool bAutoACK, long nTimeout)
{
// 发包
uint32 nSeq = _GetAvailableSEQ();
RUDPHeader header(nFlags, nBufLen, nSeq, nAck, 0);
Memory::CDataChunk packet(&header, sizeof(RUDPHeader));
packet.AppendWithoutLen(pBuf, nBufLen);
_SendDataOnly(packet.Data(), packet.Size(), saTarget);

// 等待回复
_WaitForReply(SendingData(header, packet, saTarget), nTimeout);

// 如果需要,发送自动回复包
ReceivedData& ack = _PeekReceivedData(nSeq);
if ( bAutoACK && (ack.Header.SEQNumber > 0) )
SendACKPacket(ack.Sender, ack.Header.SEQNumber);

// 返回接收到的数据
return _PopReceivedData(nSeq);
}

void CRUDPSocket::SendUniPacket(const void* pBuf, int nBufLen, const sockaddr_in& saTarget, uint32 nAck, uint16 nFlags)
{
// 发包
RUDPHeader header(nFlags, nBufLen, 0, nAck, 0);
Memory::CDataChunk packet(&header, sizeof(RUDPHeader));
packet.AppendWithoutLen(pBuf, nBufLen);
_SendDataOnly(packet.Data(), packet.Size(), saTarget);
}

void CRUDPSocket::SendACKPacket(const sockaddr_in& saTarget, uint32 nAck, uint16 nFlags)
{
SendUniPacket(NULL, 0, saTarget, nAck, 0);
}


void CRUDPSocket::OnReceive(int nErrorCode)
{
if (nErrorCode == WSAENETDOWN)
{
_OnReceiveError(_T("接受数据时发生错误!"));
return;
}

// 收包
char szBuffer[MAX_PACKET_SIZE] = "";
sockaddr_in saSender;
int nTmp = sizeof(sockaddr_in);
int nReceived = CSocket::ReceiveFrom(szBuffer, MAX_PACKET_SIZE, (sockaddr*)&saSender, &nTmp);
if (nReceived == SOCKET_ERROR)
{
_OnReceiveError(_T("接受数据时发生错误!"));
return;
}

// 分析得到报头、数据
RUDPHeader header(szBuffer, sizeof(RUDPHeader));
ReceivedData data(header,
Memory::CDataChunk(szBuffer + sizeof(RUDPHeader), nReceived - sizeof(RUDPHeader)),
saSender);

// 如果需要,写入接收队列
uint32 nAck = header.ACKNumber;
if ((nAck > 0) && _IsSEQExists(nAck))
{
m_mapReceived.insert( ReceivedDataMap::value_type(nAck, data) );
}
else
_OnReceivePacket(data);
}

void CRUDPSocket::_OnReceiveError(const TCHAR* szErr)
{
// do nothing
}

void CRUDPSocket::_WaitForReply(const SendingData& info, long nTimeout)
{
const int CHECK_INTERVAL = 200;
if (nTimeout == 0) nTimeout = m_nTimeOut;

// 取得 Sequence Number
uint32 nSeq = info.Header.SEQNumber;

// 写入发送队列
m_mapSending.insert( SendingDataMap::value_type(nSeq, info) );

// 这里实现了重试机制
int nMax = ( nTimeout / CHECK_INTERVAL );
for (int i=0; i < m_nRetryCount; ++i)
{
// 轮询等待接受到ACK包
for (int j=0; j < nMax; ++j)
{
if (_IsACKReceived(nSeq)) return;

::Sleep(CHECK_INTERVAL);
Easiware::Win32::CSystemEx::DoEvents();
}

// 如果没有成功,重新发包,再次尝试
SendingData& data = _GetSendingData(nSeq);
_SendDataOnly(data.Packet.Data(), data.Packet.Size(), data.Target);
}

// 没有收到ACK包,只好将该包从发送队列中删除,并报告错误
m_mapSending.erase(nSeq);
throw Net::CSocketTimeoutException();
}

// 确保得到不重复的Sequence Number
uint32 CRUDPSocket::_GetAvailableSEQ() const
{
for (uint32 nSeq=1; _IsSEQExists(nSeq) || _IsACKReceived(nSeq); ++nSeq);
return nSeq;
}

// 判断当前是否已经存在指定的Sequence Number
bool CRUDPSocket::_IsSEQExists(uint32 nSeq) const
{
return ( m_mapSending.find(nSeq) != m_mapSending.end() );
}

// 判断是否已经收到ACK包
bool CRUDPSocket::_IsACKReceived(uint32 nSeq) const
{
return ( m_mapReceived.find(nSeq) != m_mapReceived.end() );
}

CRUDPSocket::SendingData& CRUDPSocket::_GetSendingData(uint32 nSeq)
{
SendingDataMap::iterator it = m_mapSending.find(nSeq);
return it->second;
}

CRUDPSocket::ReceivedData& CRUDPSocket::_PeekReceivedData(uint32 nSeq)
{
ReceivedDataMap::iterator it = m_mapReceived.find(nSeq);
return it->second;
}

CRUDPSocket::ReceivedData CRUDPSocket::_PopReceivedData(uint32 nSeq)
{
CRUDPSocket::ReceivedData data(_PeekReceivedData(nSeq));

m_mapSending.erase(nSeq);
m_mapReceived.erase(nSeq);

return data;
}

void CRUDPSocket::_SendDataOnly(const void* pBuf, int nBufLen, const sockaddr_in& saTarget)
{
int nSended = CSocket::SendTo(pBuf, nBufLen, (const sockaddr*)&saTarget, sizeof(sockaddr));
if (nSended == SOCKET_ERROR)
throw Net::CSocketException(_T("发送数据时发生错误!"));
}

}
}

} // namespace Easiware
回复
balloy 2005-09-21
2、核心类

RUDPSocket.h

#include <map>
#include <afxsock.h>
#include <Easiware/RUDP/RUDPHeader.h>
#include <Easiware/Memory/DataChunk.h>
#include <Easiware/Net/SocketException.h>


namespace Easiware{

namespace RUDP
{
namespace MFC
{
/// RUDP:Reliable UDP,基于UDP实现了可靠的传输
class CRUDPSocket : public CSocket
{
private:
using CSocket::Accept;
using CSocket::Bind;
using CSocket::Connect;
using CSocket::Listen;
using CSocket::Receive;
using CSocket::ReceiveFrom;
using CSocket::Send;
using CSocket::SendTo;
using CSocket::Create;

protected: // SendingData
struct SendingData
{
public:
RUDPHeader Header;
Memory::CDataChunk Packet;
sockaddr_in Target;
public:
SendingData(const RUDPHeader& header, const Memory::CDataChunk& packet, const sockaddr_in& saTarget)
: Header(header), Packet(packet), Target(saTarget)
{}
};
typedef std::map<uint32, SendingData> SendingDataMap;

protected: // ReceivedData
struct ReceivedData
{
public:
RUDPHeader Header;
Memory::CDataChunk Payload;
sockaddr_in Sender;
public:
ReceivedData(const RUDPHeader& header, const Memory::CDataChunk& data, const sockaddr_in& saSender)
: Header(header), Payload(data), Sender(saSender)
{}
};
typedef std::map<uint32, ReceivedData> ReceivedDataMap;

public:
CRUDPSocket()
: m_nRetryCount(1)
, m_nTimeOut(6000)
{}
virtual ~CRUDPSocket() {}

public:
/// 创建Socket并绑定端口,开始侦听
void CreateSocket(unsigned short nPort = 0);

/// 发送数据(要求接收方发送响应包), 返回接受到的回应包
ReceivedData SendPacket(const void* pBuf, int nBufLen, const sockaddr_in& saTarget, uint32 nAck = 0, uint16 nFlags = 0, bool bAutoACK = true, long nTimeout = 0);

/// 发送单向数据(不要求接收方发送响应包)
void SendUniPacket(const void* pBuf, int nBufLen, const sockaddr_in& saTarget, uint32 nAck = 0, uint16 nFlags = 0);

void SendACKPacket(const sockaddr_in& saTarget, uint32 nAck = 0, uint16 nFlags = 0);

public:
long GetRetryCount() const { return m_nRetryCount; }
void SetRetryCount(long v) { m_nRetryCount = v; }

/// in milliseconds
long GetTimeout() const { return m_nTimeOut; }
void SetTimeout(long v) { m_nTimeOut = v; }

private: // implements of CSocket
virtual void OnReceive(int nErrorCode);

protected: // virtual functions
virtual void _OnReceivePacket(ReceivedData& data) = 0;
virtual void _OnReceiveError(const TCHAR* szErr);

protected:
SendingData& _GetSendingData(uint32 nSeq);

ReceivedData& _PeekReceivedData(uint32 nSeq);
ReceivedData _PopReceivedData(uint32 nSeq);

void _SendDataOnly(const void* pBuf, int nBufLen, const sockaddr_in& saTarget);

private:
uint32 _GetAvailableSEQ() const;
bool _IsSEQExists(uint32 nSeq) const;

bool _IsACKReceived(uint32 nSeq) const;

void _WaitForReply(const SendingData& info, long nTimeout);

protected:
SendingDataMap m_mapSending;
ReceivedDataMap m_mapReceived;

private:
long m_nTimeOut;
long m_nRetryCount;
};
}
}

} // namespace Easiware


回复
balloy 2005-09-21
1、部分头文件定义


RUDPHeader.h

#include <assert.h>
#include <Easiware/RUDP/Type.h>
#include <Easiware/RUDP/Flag.h>

namespace Easiware{

namespace RUDP
{
const int MAX_PACKET_SIZE = 16384; //16K

#pragma pack(1)
struct RUDPHeader
{
public:
uint16 Flags;
uint16 DataLen;
uint32 SEQNumber;
uint32 ACKNumber;
uint32 CheckSum;
public:
RUDPHeader(uint16 nFlags = 0, uint16 nLen = 0, uint32 nSeq = 0, uint32 nAck = 0, uint32 nSum = 0)
: Flags(nFlags), DataLen(nLen), SEQNumber(nSeq), ACKNumber(nAck), CheckSum(nSum)
{}

RUDPHeader(const void* pBuffer, size_t nBufferSize)
{
if (nBufferSize > sizeof(RUDPHeader))
nBufferSize = sizeof(RUDPHeader);
memcpy(this, pBuffer, nBufferSize);
}
};
#pragma pack()
}

} // namespace Easiware


Type.h

namespace Easiware{

namespace RUDP
{
typedef unsigned short uint16;
typedef unsigned long uint32;
}

} // namespace Easiware


Flag.h
//暂无定义
回复
HYWServer 2005-09-21
QQ的也是用的UDP吧?
zhchyg@163.com
谢谢!
回复
balloy 2005-09-21
还有一点,我发现我的代码在传输文件时,效率实在不高,没有什么好的解决办法。不过,这样就可以理解qq传输文件为什么要用tcp了,:)
回复
balloy 2005-09-21
我有一份,是继承CSocket实现的,但是不能把代码给你,只能给你片段,还需要吗?
回复
54783szg 2005-09-20
http://www.vckbase.net/document/viewdoc/?id=440
回复
HYWServer 2005-09-20
up
回复
HYWServer 2005-09-13
upup
回复
hailiang 2005-09-13
如果只是一对一:
发送方:
1。文件开始请求,包含文件共分的包数,等对方应答。
2。读文件 延迟 发送 直到文件结束。(至于包大小,延迟时间可以测试找到丢包相对少得合适数据)
3。是否可以结束请求,等待对方应答,缺哪些包传哪些包,直到结束。

接受方:
1。收到开始请求,准备接受数据
2。接受数据写入文件,并统计哪些包已经接受了
3。收到结束请求时,监察是否全部接受了,把没有接受到的包编号全部发出,直到全部接收到响应一个结束。
回复
hailiang 2005-09-13
自己实现把,又不难。
其实使用udp进行文件传输最好得用途是在一对多才有效率,否则还是用tcp
回复
softrain 2005-09-13
参照TCP,双方保存缓冲队列,序列号,确认,超时重传等。
回复
HYWServer 2005-09-13
是不是发送方每发送一包数据就等待对方的应答?
而接收方只有受到数据才发送一份确认应答?
回复
flashboy 2005-09-13
是我自己原来写的一个DEMO。 自己曾经测试传5000M的文件,全部正常。 不过由于是DEMO,重在实现原理,对效率照顾不多, 每次发文件数据都只发256个字节,这个太少了。 如果更高一些可能会快很多。
回复
HYWServer 2005-09-12
zhchyg@163888.net
回复
HYWServer 2005-09-12
谁有呀?
回复
相关推荐
UDP可靠传输那些事
我最开始接触udp可靠传输大约是在2005年,因为那时候开发FtpAnywhere,由于路由的映射和网关nat处理方面,认为udp具有天生优势,因此开始编写自己的udp可靠传输协议,好象那个时候已经了udt,我也下了源代码看...
python实现UDP协议下的文件传输
主要为大家详细介绍了python实现UDP协议下的文件传输,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
实现UDP可靠文件传输
在网上搜到的C#实现的UDP文件传输代码,分享给大家。局域网下速度能达到5,6M,效率还可以
基于UDP编写协议实现可靠传输
UDP是一种面向无连接的传输协议,可以理解为对某个地址寄一封信,只要双方地址填对,信就可以成功送出去,但对方能不能收到这份信,那就不一定了,可能信在传输的过程中丢了,也可能接收方没有去查收它。总之,UDP...
C#_UDP可靠文件传输
与网上盛传的UDP可靠传输传输控制策略不同,底层采用完成端口模式Socket。 实现可靠传输,源码中包含打洞代码,只有普通打洞,没有端口猜测,打洞功能没有加入demo中。 如更好的建议希望通知我,到空间留言。 或...
UDP协议学习:利用UDP协议传输文件
中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768 [1] 是UDP的正式规范。UDP在IP报文的...
UDP实现可靠文件传输
自己写的额外代码来保障UDP可靠文件传输 解决UDP传输丢包问题。
JAVA上百实例源码以及开源项目源代码
JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很帮助。...
UDP多客户端聊天文件传输源码
简单实现代码
UDP实现可靠文件传输.doc
UDP实现可靠文件传输.doc UDP实现可靠文件传输.doc
UDP数据包可靠传输实现方案
本文的主要工作是解决网关B下主机和网关C下主机之间的udp数据包可靠传输问题,采用基于udp可靠传输协议UDT来实现udp数据包的可靠传输。网关B下的客户端A是发送udp数据包的请求端,网关C下的服务器D是udp数据包的...
基于UDP文件传输 TCPIP课程作业 包括实验报告
文件为TCP/IP课程作业,局域网中基于UDP协议的文件传输,本程序为dos窗口命令行操作,全部代码均为自己编写,无抄袭 文件中包含:源文件+可执行文件+实验报告
基于java socket使用tcp udp进行简易控制台命令与文件传输
2) 基于Java Socket TCP和UDP实现一个简易的网络文件服务程序,包含服务器端FileServer和客户端FileClient; 3) 服务器端启动时需传递root...7) 服务器端支持多用户并发访问,不用考虑文件过大或UDP传输可靠的问题。
怎样实现UDP可靠传输
相对于TCP,由于UDP是面向无连接、不可靠传输协议。 如果我们要用UDP去实现可靠传输,则需要解决两个问题:丢包和后发先至(包的顺序)。解决方法: 1)给数据包编号,按照包的顺序接收并存储; 2)接收端...
Python在应用层实现UDP协议的可靠传输
使用UDP协议传输文件,在应用层实现可靠传输,避免传输层不保序和可能丢包造成的不可靠传输问题。 基本思路: 在发送端使用一个线程把要发送的内容进行分块传输,发送时携带每个分块的序号,同时使用另外一个线程...
ReliableFileTransferProtocol:通过不可靠UDP进行简单可靠文件传输-源码
简单的发送和接收传输级别代码,用于通过UDP实现可靠文件传输协议。 基础通道不可靠,可能会随机破坏,丢弃甚至重新排序数据包。 速度 第一名的CS2105(介绍计算机网络)速度竞赛AY15 / 16 SEM1。 (在平地机上...
TCP 和 UDP 的区别?TCP 数据传输过程中怎么做到可靠的?
TCP与UDP区别总结: 1、TCP面向连接(如打电话要先拨号...UDP尽最大努力交付,即不保 证可靠交付 3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的 UDP没有拥塞控制,因此网络出现拥...
基于TCPUDP文件传输
基于双协议(TCP\UDP)的文件传输,并实现了UDP可靠
udp可靠传输那些事之游戏篇
这篇文章是udp可靠传输那些事的续篇,针对udp可靠传输在游戏类的应用的优点和缺点以及原理,进行了详细的分析.
基于UDP协议可靠传输协议QUIC协议和golang server代码和client代码
QUIC 的基本特点基于UDP的多路传输(单连接下); 极低的等待时延(相比于TCP的三次握手); 快速迭代更新; 开源于Chromium项目中。 首先,QUIC为 传输层 协议,与TCP、UDP、SCTP同级。所以肯定会 在一定范围...
参考资料 | 用python实现基于UDP可靠文件传输
[代码笔记] python 之网络编程: 使用udp 发送音频文件 超时重传: Python3.x:简单时间调度Timer(间隔时间执行) vscode使用: 非常全的VsCode快捷键 python全局变量与局部变量: Python语法基础——关于全局...
几种常见的可靠UDP传输协议(包含C#实现)
几种UDP网络库的整理Raknet,UDT,ENet,lidgren-network-gen3 http://blog.csdn.net/u014630768/article/details/34895367 UDT库 https://sourceforge.net/projects/udt/?source=directory C#包装:...
Linux网络编程之基于UDP实现可靠文件传输示例
相对于TCP,由于UDP是面向无连接、不可靠的传输协议,所以我们需要考虑丢包和后发先至(包的顺序)的问题,所以我们想要实现UDP传输文件,则需要解决这两个问题。方法就是给数据包编号,按照包的顺序接收并存储,...
比较TCP/UDP传输文件时所用时间
分别使用TCP、UDP传输文件,比较两者的传输时间。 二、实验目的 1.掌握TCP、UDP的工作原理; 2.掌握TCP/UDP的简单代码实现方式; 三、实验内容 1.TCPClient核心代码 2.TCPServer核心代码 3.UDPClient核心代码 4...
VC++ UDP实现可靠传输(文件) UDX协议
关见字: UDP UDX RTP,RUDP UDP可靠传输,UDP文件传输,P2P UDP文件传输   一种基于UDP的可靠传输协议-UDX   UDX作为一个新的协议,从研发到成功经力了相当长一段时间. ...
基于UDP可靠性高速传输(大文件)的实现(一)
TCP 协议和 UDP 协议是 TCP / I P协议栈中的... TCP 协议一般应用在数据传输量大或可靠性要求高的场合 (例如: 文件传输 ); UDP协议则一般是应用在数据传输量不大且可靠性要求不高的场合. 然而, 在实践中却会经常碰到...
基于UDP的多播(组播)文件传输
此次的课程设计通过借鉴网上的信息(前人种树后人乘凉,...主要代码: public class MULTICAST { private String cachePath="D:\\Network\\CC1\\"; SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");//...
实现可靠UDP传输
实现可靠UDP传输。虽然名字叫UDT,但是和UDT有着本质区别(主要是不想费脑筋取名字),它可以像UDP一样实现多点自由传输,而无需像UDT那样必须建立服务器,然后等待连接然后在传输。 所用原理就是简单的 确认 + 超时...
QT 编程学习记录のUDP文件传输
UDP:是一种无连接,不可靠传输层协议,在传输和接收之前不需要握手操作,建立套接字之后,发送端直接进行文件的读取和发送,而接收端循环检测是否数据可读,可读就读取数据并写入新建的文件。 重点在于套接字...
Java初级从入门到精通
课程分为:J2SE 基础阶段,中级阶段,阶段; 课间会讲解一些小程序的开发:如:猜拳游戏,模拟银行柜员机程序,退休金结算程序等.
发帖
网络编程
创建于2007-09-28

1.8w+

社区成员

VC/MFC 网络编程
申请成为版主
帖子事件
创建了帖子
2005-09-12 03:13
社区公告
暂无公告