⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 传输.txt

📁 MFC类下的winsock多线程实现文件传输
💻 TXT
字号:
//1:显示文件进度


//2:可以随时终止传输过程


//发送数据线程


UINT SendDataThread(LPVOID lpParam);


//接收数据线程


UINT ReceiveDataThread(LPVOID lpParam);


//发送数据按钮消息响应函数


void CTzg004Dlg::OnButtonSend() 


{


     // TODO: Add your control notification handler code here


     //初始化数据发送结束标志


     m_bSendEnd=FALSE;


     //初始化数据接收结束标志


     m_bRecEnd=FALSE;


     //更新对话框数据


     UpdateData(TRUE);


     //打开文件对话框


     CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,


          "所有文件 (*.*)|*.*||");


     if(dlg.DoModal()==IDOK)


     {


         m_strFileName=dlg.GetPathName();


          //开始发送数据线程


         AfxBeginThread(SendDataThread,this,THREAD_PRIORITY_NORMAL);


     }


}


//接收数据按钮消息响应函数


void CTzg004Dlg::OnButtonReceive() 


{


     // TODO: Add your control notification handler code here


     //初始化数据发送结束标志


     m_bSendEnd=FALSE;


     //初始化数据接收结束标志


     m_bRecEnd=FALSE;


     UpdateData(TRUE);


     //开始接收数据线程 


     AfxBeginThread(ReceiveDataThread,this,THREAD_PRIORITY_NORMAL);


}


//终止发送按钮消息响应


void CTzg004Dlg::OnButtonSendEnd() 


{


     // TODO: Add your control notification handler code here


     //设置发送数据结束标志


     m_bSendEnd=TRUE;


}


//终止接收按钮消息响应


void CTzg004Dlg::OnButtonRecEnd() 


{


     // TODO: Add your control notification handler code here


     //设置接收数据结束标志


     m_bRecEnd=TRUE;


}


UINT SendDataThread(LPVOID lpParam)


{


     CTzg004Dlg *pDlg=(CTzg004Dlg *)lpParam;


     CFile file;


     if( !file.Open(pDlg->m_strFileName, CFile::modeRead) )


     {


         AfxMessageBox("打开文件出错!");


          return 0;


     }


     CSocket sockTemp;


     CString str,str1;


     sockTemp.Create(pDlg->m_iDataPort1); //得到端口号


     sockTemp.Listen(1);//只接受一个连接


     CSocket sockSend;


     //设置发送按钮禁止


     pDlg->GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(FALSE);


     sockTemp.Accept(sockSend);//注意,sockTemp已交了自己的指针地址到sockSend,故不用Close


     //打开发送终止按钮


     pDlg->GetDlgItem(IDC_BUTTON_SEND_END)->EnableWindow(TRUE);


     


     


     int iBufSize = 1024 * 5;  


     int iSize = iBufSize;


     LPBYTE pBuf = new BYTE[iBufSize];     


     


     DWORD dwTemp = 0;


     BOOL bTest = sockSend.AsyncSelect(0);//由于CSocket实际是异步,将它变为同步(阻塞)方式。


     sockSend.IOCtl( FIONBIO, &dwTemp);//用IOCtl要将AsyncSelect的第一个参数为0,参看MSDN


     


     UINT uiLength = file.GetLength();


     sockSend.Send(&uiLength, 4);//传送文件大小到接收方(Client端)


     


     int iNumByte;


     UINT uiTotal = 0;


     while(uiTotal < uiLength)


     {


          int iEnd=pDlg->m_bSendEnd;


          //传送发送端状态(是否结束)


         iNumByte = sockSend.Send(&iEnd, sizeof(int));


          //发送错误


         if(iNumByte == SOCKET_ERROR)


          {


              AfxMessageBox("发送错误!");


              goto ExitLable1;


          }else if(iEnd==1)//发送端终止


          {


              AfxMessageBox("发送端终止");


              goto ExitLable1;


          }        


          //读取文件内容


         if((int)(uiLength - uiTotal) < iBufSize)


              iSize = uiLength - uiTotal;//当小于缓冲区iTEST时的处理


         iSize=file.Read(pBuf , iSize);//得到读取的字节数


          int iCount=0;


          //发送定长文件数据


         while(iCount<iSize)


          {


              iNumByte = sockSend.Send(pBuf, iSize-iCount);//注意iNumByte为实际的发送字节数,不要以iSize为准


              if(iNumByte == SOCKET_ERROR)


              {


                   AfxMessageBox("发送错误!");


                   goto ExitLable1;


              }


              iCount+=iNumByte;


              if(iCount<iSize)


              {


                   file.Seek(iSize-iCount,CFile::current);


              }


          }


          uiTotal += iCount;


          //设置发送数据进度条


         pDlg->m_CtrlProgressSend.SetPos(int(((double)uiTotal/uiLength)*100));


         str.Format("发送进度:%d%%",int(((double)uiTotal/uiLength)*100));


          //表明发送数据百分比


         pDlg->GetDlgItem(IDC_STATIC_SEND)->GetWindowText(str1);


         if(str1!=str)


              pDlg->GetDlgItem(IDC_STATIC_SEND)->SetWindowText(str); 


     }


     //发送文件成功


     AfxMessageBox("发送文件成功!");


ExitLable1:


     delete[] pBuf;


     file.Close();


     sockSend.Close();


     pDlg->m_CtrlProgressSend.SetPos(0);//恢复进度


     pDlg->GetDlgItem(IDC_BUTTON_SEND_END)->EnableWindow(FALSE);//设置发送结束按钮禁止


     pDlg->GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(TRUE);//设置发送按钮正常


     pDlg->GetDlgItem(IDC_STATIC_SEND)->SetWindowText("发送进度:"); //恢复提示进度


     return 0;


}



UINT ReceiveDataThread(LPVOID lpParam)


{


     CTzg004Dlg *pDlg=(CTzg004Dlg *)lpParam;


     //保存文件对话框


     CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,


          "所有文件 (*.*)|*.*||");


     while(dlg.DoModal()!=IDOK)


     {


         AfxMessageBox("选择文件出错,请重新选择!");


     }         


     CString str,str1,str2;


     CSocket sockRecv;


     sockRecv.Create();


     pDlg->m_CtrlIPSend.GetWindowText(str);//得到发送端IP地址


     pDlg->GetDlgItem(IDC_BUTTON_RECEIVE)->EnableWindow(FALSE);//禁止接收按钮


     while(sockRecv.Connect(str,pDlg->m_iDataPort2)==0)//连接发送方地址,若上网,可改为实际IP地址,端口要跟Server端相同。


     {


         Sleep(50);


     }


     pDlg->GetDlgItem(IDC_BUTTON_REC_END)->EnableWindow(TRUE);//打开终止接收按钮


     str2=dlg.GetPathName();//得到文件名


     CFile file;


     file.Open(str2, CFile::modeCreate | CFile::modeWrite);


     BOOL bFileFail=FALSE;


     DWORD dwTemp = 0;


     sockRecv.AsyncSelect(0);


     sockRecv.IOCtl( FIONBIO, &dwTemp);//变为阻塞方式


     


     UINT uiLength;


     sockRecv.Receive(&uiLength, 4);//接收发方(Server端)的文件大小


     int iBufSize = 1024 * 5;


     int iSize = iBufSize;


     LPBYTE pBuf = new BYTE[iBufSize];


     int iNumByte;


     UINT uiTotal = 0;


     while(uiTotal < uiLength)


     {


          int iEnd=0;


          //接收端终止


         if(pDlg->m_bRecEnd)


          {


              AfxMessageBox("接收端终止!");


              goto ExitLable2;


          }


          //接收发送端状态数据


         iNumByte=sockRecv.Receive(&iEnd, sizeof(int));


         if(iNumByte == SOCKET_ERROR)


          {


              AfxMessageBox("接收信号错误!");


              goto ExitLable2;


          }


          //发送端终止


         if(iEnd==1)


          {


              AfxMessageBox("发送端终止!");


              goto ExitLable2;


          }




         if((int)(uiLength - uiTotal) < iBufSize)


              iSize = uiLength - uiTotal;


          int iCount=0;


          //读取定长数据


         while(iCount<iSize)


          {


              iNumByte = sockRecv.Receive(pBuf, iSize-iCount);


              if(iNumByte == SOCKET_ERROR)


              {


                   AfxMessageBox("接收错误!");


                   goto ExitLable2;


              }


              iCount+=iNumByte;


              file.Write(pBuf, iNumByte);


          }


          uiTotal += iCount;//以实际接收字节为准


          //设置接收进度


         pDlg->m_CtrlProgressRec.SetPos(int(((double)uiTotal/uiLength)*100));


         str.Format("接收进度:%d%%",int(((double)uiTotal/uiLength)*100));


          //显示接收进度百分比


         pDlg->GetDlgItem(IDC_STATIC_REC)->GetWindowText(str1);


         if(str1!=str)


              pDlg->GetDlgItem(IDC_STATIC_REC)->SetWindowText(str);


     }


     //接收文件成功


     AfxMessageBox("接收文件成功!");


     bFileFail=TRUE;


ExitLable2:


     delete[] pBuf;


     file.Close();


     //文件接收失败,则删除接收文件


     if(!bFileFail)


     {


         CFile::Remove( str2 );


     }


     sockRecv.Close();


     pDlg->m_CtrlProgressRec.SetPos(0);//恢复接收进度


     //禁止终止接收按钮


     pDlg->GetDlgItem(IDC_BUTTON_REC_END)->EnableWindow(FALSE);


     //打开接收按钮


     pDlg->GetDlgItem(IDC_BUTTON_RECEIVE)->EnableWindow(TRUE);


     //恢复提示进度


     pDlg->GetDlgItem(IDC_STATIC_REC)->SetWindowText("接收进度:");


     return 0;


}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -