⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filetransdlg.cpp

📁 局域网内简单的TCP/IP文件互传程序
💻 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)&param);	//开始保存文件进程
	}
	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 + -