利用socket传文件

 

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


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值