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