udp可靠文件传输实现(基于滑动窗口机制)

本文档详细介绍了如何使用滑动窗口机制来实现在UDP上可靠的文件传输。通过滑动窗口协议,确保数据包的正确发送与确认,从而克服UDP的不可靠性。文中提供了一个具体的UDP文件传输的Demo,包括发送方和接收方的核心代码,展示了如何处理数据包的发送、确认、重传以及窗口管理。
摘要由CSDN通过智能技术生成

老板逼着让写一个基于UDP可靠通信的demo以作为其网络课程的课件内容之一来给学生演示

 

 

dup是不可靠的,为了实现可靠文件传输,需要加入额外的机制来确保可靠,在此选用了滑动窗口机制。

 

 

 

滑动窗口介绍:

 

滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口。发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。不同的滑动窗口协议窗口大小一般不同。发送方窗口内的序列号代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧。下面举一个例子(假设发送窗口尺寸为2,接收窗口尺寸为1):


   分析:①初始态,发送方没有帧发出,发送窗口前后沿相重合。接收方0号窗口打开,等待接收0号帧;②发送方打开0号窗口,表示已发出0帧但尚确认返回信息。此时接收窗口状态不变;③发送方打开0、1号窗口,表示0、1号帧均在等待确认之列。至此,发送方打开的窗口数已达规定限度,在未收到新的确认返回帧之前,发送方将暂停发送新的数据帧。接收窗口此时状态仍未变;④接收方已收到0号帧,0号窗口关闭,1号窗口打开,表示准备接收1号帧。此时发送窗口状态不变;⑤发送方收到接收方发来的0号帧确认返回信息,关闭0号窗口,表示从重发表中删除0号帧。此时接收窗口状态仍不变;⑥发送方继续发送2号帧,2号窗口打开,表示2号帧也纳入待确认之列。至此,发送方打开的窗口又已达规定限度,在未收到新的确认返回帧之前,发送方将暂停发送新的数据帧,此时接收窗口状态仍不变;⑦接收方已收到1号帧,1号窗口关闭,2号窗口打开,表示准备接收2号帧。此时发送窗口状态不变;⑧发送方收到接收方发来的1号帧收毕的确认信息,关闭1号窗口,表示从重发表中删除1号帧。此时接收窗口状态仍不变。

    若从滑动窗口的观点来统一看待1比特滑动窗口、后退n及选择重传三种协议,它们的差别仅在于各自窗口尺寸的大小不同而已。1比特滑动窗口协议:发送窗口=1,接收窗口=1;后退n协议:发窗口>1,接收窗口>1;选择重传协议:发送窗口>1,接收窗口>1。

 

 

demo演示截图:

 

 

 

 

核心代码:

发送方:(接收和发送线程函数)

 

bool CUDPTrsmtFile::ServerSend()
{
 if(!s_SendHoleMsg())
  return false;

 // 设置文件指针位置,指向上次已发送的大小
 SetFilePointer(m_hFile, m_dwSend, NULL, FILE_BEGIN);

 int  ret;
 int  nPacketCount = 0;
 DWORD dwRet;
 SendBuf sendbuf;
 DWORD dwRead;
 DWORD dwReadSize;

 SendBuf* pushbuf;

 SetEvent(m_hEvent);

 

 //若已发送大小小于文件大小并且发送窗口前沿等于后沿,则继续发送
 //否则退出循环
 m_sumPacket = (m_dwFileSize - m_dwSend)/(MAXBUF_SIZE);

 if(m_dwSend < m_dwFileSize)  // 文件没有传输完时才继续传输
 {
  while(1)
  {
   dwRet = WaitForSingleObject(m_hEvent, 1000);
   if(dwRet == WAIT_FAILED)
   {
    CString temp="等待发送信号灯出错!";
    SendMessage(the_hWnd,ECHO_MSG,0,LPARAM(&temp));
    SendMessage(the_hWnd,FINISHEDTRANS_MSG,0,0);
    return false;
   }
   else if(dwRet == WAIT_TIMEOUT)
   {
    //重发
    int ackindex=0;
    ::EnterCriticalSection(&m_csQueue);  // 进入m_bufqueue的排斥区
    ackindex=m_bufqueue.front()->index;
    ret = m_hsocket.hsendto((char*)m_bufqueue.front(), sizeof(sendbuf));
    ::LeaveCriticalSection(&m_csQueue);  // 退出m_bufqueue的排斥区
    if(ret == SOCKET_ERROR)
    {
     CString temp="发送窗口中的数据包发送失败,重发数据包!";
     SendMessage(the_hWnd,ECHO_MSG,0,LPARAM(&temp));
     continue;
    }

    CString temp;
    temp.Format("等待ACK确认消息超时,重发发送窗口的第 %d 个数据包",ackindex);
    SendMessage(the_hWnd,ECHO_MSG,0,LPARAM(&temp)

  • 0
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 42
    评论
评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值