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