网页功能: 加入收藏 设为首页 网站搜索  
Socket传输文件示例
发表日期:2003-12-02作者:bluebohe[] 出处:  

//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;

}

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 Socket传输文件示例
本类热点文章
  P2P之UDP穿透NAT的原理与实现
  Socket传输文件示例
  Socket传输文件示例
  微软ping程序源代码完整版
  Windows Socket API 使用经验
  MSXML 解析 XML
  VC中ftp协议实现多线程断点续传
  一个对Winsock 完成端口模型封装的类
  一个对Winsock 完成端口模型封装的类
  点对点(P2P)多线程断点续传的实现
  编程建立IIS站点和虚拟目录
  Windows网络编程经验小结(1)
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.0042