时间问题,在转载这个代码前,没有经过测试,大家自己测试一下,如果有什么问题,再跟我们联系。
//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;
}