📄 filetransdlg.cpp
字号:
// FileTransDlg.cpp : 主文件
#include "stdafx.h"
#include "FileTrans.h"
#include "FileTransDlg.h"
#include "TransStatus.h"
#include "FileArrive.h"
#include "CRCFromASM.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//定义常量宏开始
#define BUFFERSIZE 65000 //每次文件传输块的大小
#define FILEPORT 5200 //文件传输端口
#define UM_CREATE_TRANSSTATUS WM_USER+105
#define UM_DELETE_DLG WM_USER+106
//定义常量宏结束
//自定义结构开始
struct SENDFILEPARAM //文件发送结构体
{
CString pathname; //路径名
CString ip; //ip地址
char filename[1024]; //文件名,注意是char[]型
CFileTransDlg * pFT; //对应的主窗口类指针
char crcvalue[9];
};
struct SAVEFILEPARAM //文件接收结构体
{
SOCKET sock; //socket
CFileTransDlg * p; //主窗口类指针
};
//自定义结构结束
//自编写函数开始
//接收并保存文件的进程
UINT SaveFile(LPVOID p)
{
SAVEFILEPARAM sp; //将无类型p传递给sp
sp.p=((SAVEFILEPARAM *)p)->p; //
sp.sock=((SAVEFILEPARAM *)p)->sock; //
CSocket sock;
sock.Attach(sp.sock); //调用sock.attach
DWORD Length; //保存文件长度
char filename[1024]; //文件名
char crcReceive[9]; //接收到的CRC值
char crcCalculate[9]; //计算出的CRC值
CString savepathname; //路径名
int modal,err;
memset(filename,0,1024); //文件名清空
err=sock.Receive(&Length,sizeof(DWORD)); //接收文件长度
if(0==err)
{
AfxMessageBox("The connection is closed.");
sock.Close();
return 0;
}
if(SOCKET_ERROR==err)
{
AfxMessageBox("socket error.");
sock.Close();
return 0;
}
err=sock.Receive(filename,1024); //接收文件名
if(0==err)
{
AfxMessageBox("The connection is closed.");
sock.Close();
return 0;
}
if(SOCKET_ERROR==err)
{
AfxMessageBox("socket error.");
sock.Close();
return 0;
}
err=sock.Receive(crcReceive,9); //接收CRC值
if(0==err)
{
AfxMessageBox("The connection is closed.");
sock.Close();
return 0;
}
if(SOCKET_ERROR==err)
{
AfxMessageBox("socket error.");
sock.Close();
return 0;
}
CFileArrive dlg; //创建"文件到达选项"的对话框
dlg.m_filename.Format("文件 %s 到达,是否接收?",filename);
if(IDCANCEL==dlg.DoModal())
{
sock.Close();
return 0;
}
CFileDialog fdlg(false,NULL,filename); //创建选择保存路径的对话框
modal=fdlg.DoModal();
if(IDCANCEL==modal)
{
sock.Close();
return 0;
}
savepathname=fdlg.GetPathName(); //提取保存路径
int finish=0;
DWORD step=0;
CFile file;
char buffer[BUFFERSIZE]; //buffer
if(0==file.Open(savepathname,CFile::modeWrite | CFile::modeCreate | CFile::typeBinary))
{ //创建文件尝试
AfxMessageBox("Open file error.");
sock.Close();
return 0;
}
CTransStatus * pTS=new CTransStatus(); //创建传输状态窗口
sp.p->SendMessage(UM_CREATE_TRANSSTATUS,(WPARAM)pTS); //发送窗口创建消息
pTS->m_progress.SetRange32(0,Length); //进度条初始化
pTS->m_progress.SetPos(0); //
DWORD timestart,timeend,time,speed;
CString s;
timestart=::GetTickCount(); //记录开始时间
s.Format("正在接收文件: %s",filename);
pTS->m_title.SetWindowText(s);
while(true)
{
finish=sock.Receive(buffer,BUFFERSIZE); //接收一个buffer的数据
if(0==finish)
break;
if(SOCKET_ERROR==finish)
{
AfxMessageBox("socket error!");
sock.Close();
sp.p->SendMessage(UM_DELETE_DLG,(WPARAM)pTS);
sp.p->SetFocus();
return 0;
}
if(pTS->m_bend) //判断用户是否取消
{
sock.Close();
sp.p->SendMessage(UM_DELETE_DLG,(WPARAM)pTS);
sp.p->SetFocus();
return 0;
}
file.Write(buffer,finish); //写入文件
step+=finish; //step加上finish的值(buffer的大小)
pTS->m_progress.SetPos(step); //进度条
timeend=::GetTickCount(); //计算速度
time=timeend-timestart; //
time/=1000; //
if(time>0)
{
speed=((step/time)>>10);
s.Format("接收速度为: %dKB/s",speed);
pTS->m_transspeed.SetWindowText(s);
}
}
file.Close();
sock.Close();
CString whole=fdlg.GetPathName();
DWORD dwCrc32;
CString m_CrcValue;
CAsm CRCINFO;
if (CRCINFO.GetFileCrc(whole, dwCrc32))
{
CString str;
str.Format(_T("%08X"), dwCrc32);
m_CrcValue=str;
}
else
{
m_CrcValue="00000000函数调用错误!";
}
for(int j=0;j<8;j++)
{
crcCalculate[j]=m_CrcValue.GetAt(j);
}
crcCalculate[8]='\0';
int IsDifferent=strcmp(crcReceive,crcCalculate);
CString re=crcReceive;
CString ca=crcCalculate;
CString crcresult="接收到的CRC32值为:"+re+",计算出的CRC32值为:"+ca;
if(0==IsDifferent)
crcresult=crcresult+",CRC32校验通过!";
else
crcresult=crcresult+",CRC32校验失败!";
AfxMessageBox(crcresult);
sp.p->SendMessage(UM_DELETE_DLG,(WPARAM)pTS); //发送关闭窗口消息
CString strfinish;
strfinish.Format("已成功接收文件 %s",filename);
AfxMessageBox(strfinish);
sp.p->SetFocus(); //主窗口选中
return 0;
}
//监听是否有文件送达的进程
UINT ListenFile(LPVOID p)
{
CFileTransDlg * pFT=(CFileTransDlg *)p; //转换p的格式,保存为pFT
CSocket sockserver; //CSocket
if (!AfxSocketInit())
{
AfxMessageBox("ListenFile AfxSocketInit() failure.");
return 0;
}
if(0==sockserver.Create(FILEPORT)) //创建端口
{
AfxMessageBox("sockserver create failure.");
return 0;
}
if(0==sockserver.Listen()) //监听
{
AfxMessageBox("sockserver listen failure.");
sockserver.Close();
return 0;
}
pFT->m_Send.EnableWindow(true); //发送文件按钮允许
while(true)
{
CSocket sockclient;
if(0==sockserver.Accept(sockclient))
{
AfxMessageBox("sockserver accept failure.");
sockserver.Close();
break;
}
SAVEFILEPARAM param;
param.sock=sockclient.Detach();
param.p=pFT;
AfxBeginThread(SaveFile,(LPVOID)¶m); //开始保存文件进程
}
sockserver.Close();
return 0;
}
//发送文件进程
UINT SendFile(LPVOID p)
{
if(!AfxSocketInit())
{
AfxMessageBox(" SendFile AfxSocketInit() failure.");
return 0;
}
CFileTransDlg *pFT=((SENDFILEPARAM *)p)->pFT;
CString ip;
char filename[1024];
char crcvalue[9];
char buffer[BUFFERSIZE];
DWORD Length;
CFile file;
memset(filename,0,1024);
strcpy(filename,((SENDFILEPARAM *)p)->filename);
strcpy(crcvalue,((SENDFILEPARAM *)p)->crcvalue);
ip=((SENDFILEPARAM *)p)->ip;
if(0==file.Open(((SENDFILEPARAM *)p)->pathname,CFile::modeRead | CFile::typeBinary))
{
return 0;
}
Length=file.GetLength();
//准备发送
CSocket socksend;
if(0==socksend.Create())
{
AfxMessageBox("Socket create failure.");
return 0;
}
if(0==socksend.Connect(ip,FILEPORT)) //socket.connect
{
AfxMessageBox("Fail to connect to %s,he may not be online.");
socksend.Close();
return 0;
}
if(SOCKET_ERROR==socksend.Send(&Length,sizeof(DWORD))) //发送文件长度
{
AfxMessageBox("Send file size error!");
socksend.Close();
return 0;
}
if(SOCKET_ERROR==socksend.Send(filename,1024)) //发送文件名
{
AfxMessageBox("Send filename error!");
socksend.Close();
return 0;
}
if(SOCKET_ERROR==socksend.Send(crcvalue,9)) //发送文件CRC值
{
AfxMessageBox("Send crcvalue error!");
socksend.Close();
return 0;
}
DWORD step=0;
int over,err;
CTransStatus * pTS=new CTransStatus();
pFT->SendMessage(UM_CREATE_TRANSSTATUS,(WPARAM)pTS); //创建文件发送窗口
pTS->m_progress.SetRange32(0,Length); //进度条
pTS->m_progress.SetPos(0);
DWORD timestart,timeend,time,speed;
CString s;
timestart=::GetTickCount();
s.Format("正在发送文件: %s",filename);
pTS->m_title.SetWindowText(s);
do
{
file.Seek(step,CFile::begin);
over=file.Read(buffer,BUFFERSIZE);
err=socksend.Send(buffer,over);
if(BUFFERSIZE>over)
break;
if(SOCKET_ERROR==err)
{
AfxMessageBox("Send file content error!");
socksend.Close();
pFT->SendMessage(UM_DELETE_DLG,(WPARAM)pTS);
pFT->SetFocus();
return 0;
}
if(pTS->m_bend)
{
socksend.Close();
pFT->SendMessage(UM_DELETE_DLG,(WPARAM)pTS);
pFT->SetFocus();
return 0;
}
step+=err;
pTS->m_progress.SetPos(step);
timeend=::GetTickCount();
time=timeend-timestart;
time/=1000;
if(time>0)
{
speed=((step/time)>>10);
s.Format("传送速度为: %dKB/s",speed);
pTS->m_transspeed.SetWindowText(s);
}
}while(true);
file.Close();
socksend.Close();
pFT->SendMessage(UM_DELETE_DLG,(WPARAM)pTS);
CString strfinish;
strfinish.Format("已成功发送文件 %s",filename);
AfxMessageBox(strfinish);
pFT->SetFocus();
delete (SENDFILEPARAM *)p;
return 0;
}
//自编写函数结束
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFileTransDlg dialog
CFileTransDlg::CFileTransDlg(CWnd* pParent /*=NULL*/)
: CDialog(CFileTransDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CFileTransDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CFileTransDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFileTransDlg)
DDX_Control(pDX, IDC_SEND, m_Send);
DDX_Control(pDX, IDC_IPADDR, m_IP);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CFileTransDlg, CDialog)
//{{AFX_MSG_MAP(CFileTransDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_SEND, OnSend)
//}}AFX_MSG_MAP
//自定义消息响应开始
ON_MESSAGE(UM_CREATE_TRANSSTATUS,OnCreateTransStatus)
ON_MESSAGE(UM_DELETE_DLG,OnDeleteDlg)
//自定义消息响应结束
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFileTransDlg message handlers
BOOL CFileTransDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
//***************************************************************************
AfxBeginThread(ListenFile,this); //主窗口初始化时,就运行文件传输监听进程
//***************************************************************************
return TRUE; // return TRUE unless you set the focus to a control
}
void CFileTransDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CFileTransDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CFileTransDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
//消息响应函数开始
void CFileTransDlg::OnSend()
{
// 获取输入的IP值并将其转化为CString ip
unsigned char *pIP;
CString ip;
DWORD dwIP;
m_IP.GetAddress(dwIP);
pIP = (unsigned char*)&dwIP;
ip.Format("%u.%u.%u.%u",*(pIP+3), *(pIP+2), *(pIP+1), *pIP);
int modal,ncount;
CString filename;
// 选择传输的文件
CFileDialog fdlg(true);
modal=fdlg.DoModal();
if(IDCANCEL==modal)
{
return;
}
SENDFILEPARAM *p=new SENDFILEPARAM;
filename=fdlg.GetFileName();
p->pathname=fdlg.GetPathName();
ncount=filename.GetLength();
CString whole=fdlg.GetPathName();
DWORD dwCrc32;
CString m_CrcValue;
CAsm CRCINFO;
if (CRCINFO.GetFileCrc(whole, dwCrc32))
{
CString str;
str.Format(_T("%08X"), dwCrc32);
m_CrcValue=str;
}
else
{
m_CrcValue="00000000函数调用错误!";
}
for(int j=0;j<8;j++)
{
p->crcvalue[j]=m_CrcValue.GetAt(j);
}
p->crcvalue[8]='\0';
memset(p->filename,0,1024);
for(int i=0;i<ncount;i++)
{
p->filename[i]=filename.GetAt(i);
}
p->pFT=this;
p->ip=ip;
::AfxBeginThread(SendFile,(LPVOID)p); //开始文件传输进程
return;
}
void CFileTransDlg::OnCreateTransStatus(WPARAM wParam,LPARAM lParam )
{
CTransStatus * p=(CTransStatus*)wParam;
p->Create(IDD_TRANSSTATUS_DIALOG,this);
p->ShowWindow(SW_SHOW);
}
void CFileTransDlg::OnDeleteDlg(WPARAM wParam,LPARAM lParam )
{
CTransStatus * p=(CTransStatus*)wParam;
p->DestroyWindow();
p=NULL;
}
//消息响应函数结束
void CFileTransDlg::OnCancel()
{
// TODO: Add extra cleanup here
CDialog::OnCancel();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -