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

📄 fileposterdlg.cpp

📁 基于UDP协议的网络文件传输源码
💻 CPP
字号:
//Download by http://www.NewXing.com
// FilePosterDlg.cpp : implementation file
//

#include "stdafx.h"
#include "FilePoster.h"
#include "FilePosterDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	CString	m_dsc;
	//}}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)
	m_dsc = _T("本程序运用UDP原理进行文件的传输,文件被分割为256B的数据块,为保证数据块的传输顺序,采用自定义Windows消息进行同步,即每接受完一个数据块给出一个消息,发送法受到消息后发送数据。");
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	DDX_Text(pDX, IDC_EDIT, m_dsc);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFilePosterDlg dialog
int CFilePosterDlg::nFileSize = 0;

CFilePosterDlg::CFilePosterDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CFilePosterDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CFilePosterDlg)
	m_filePath = _T("");
	m_recv = _T("接受进度:");
	m_send = _T("发送进度:");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_file = NULL;
	m_posting = false;
}

void CFilePosterDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFilePosterDlg)
	DDX_Control(pDX, IDC_PROGRESS_RECV, m_progress_r);
	DDX_Control(pDX, IDC_PROGRESS_SEND, m_progress);
	DDX_Control(pDX, IDC_IP_ADDR, m_IPAddr);
	DDX_Text(pDX, IDC_FILE_PATH, m_filePath);
	DDX_Text(pDX, IDC_RECV, m_recv);
	DDX_Text(pDX, IDC_SEND, m_send);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CFilePosterDlg, CDialog)
	//{{AFX_MSG_MAP(CFilePosterDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_FIND_FILE, OnFindFile)
	ON_COMMAND(ID_MENU_SEND, OnMenuSend)
	ON_COMMAND(ID_MENU_QUIT, OnMenuQuit)
	ON_COMMAND(ID_ABOUT, OnAbout)
	ON_COMMAND(ID_MENU_FIND, OnMenuFind)
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_READY_TO_RECEIVE, OnReadyToRecv)	//自定义消息,用于分块发送文件
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFilePosterDlg message handlers
struct RECVPARAM
{
	HWND hWnd;
	SOCKET sock;
};

BOOL CFilePosterDlg::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
//	m_progress.SetRange(0, 10000);
//	m_progress_r.SetRange(0, 10000);
	m_progress.SetStep(1);
	m_progress_r.SetStep(1);
	
/***********************************************************************/
	m_socket=socket(AF_INET,SOCK_DGRAM,0);
	if(INVALID_SOCKET==m_socket)
	{
		MessageBox("套接字创建失败!");
		return FALSE;
	}
	SOCKADDR_IN addrSock;
	addrSock.sin_family=AF_INET;
	addrSock.sin_port=htons(6800);
	addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

	int retval;
	retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
	if(SOCKET_ERROR==retval)
	{
		closesocket(m_socket);
		MessageBox("绑定失败!");
		return FALSE;
	}
	//产生一个用于接收数据的线程
	struct RECVPARAM *pRecvParam=new RECVPARAM;
	pRecvParam->sock=m_socket;
	pRecvParam->hWnd=m_hWnd;
	HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
	CloseHandle(hThread);
/**************************************************************************/	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CFilePosterDlg::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 CFilePosterDlg::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 CFilePosterDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

//接收线程的回调函数
DWORD WINAPI CFilePosterDlg::RecvProc(LPVOID lpParameter)
{
	SOCKET sock=((RECVPARAM*)lpParameter)->sock;
	HWND hWnd=((RECVPARAM*)lpParameter)->hWnd;
	delete lpParameter;	

	SOCKADDR_IN addrFrom;
	int len=sizeof(SOCKADDR);
	char recvBuf[0x112];		//256+17字节的缓冲
	char fileName[0x100];
	int retval, i;
	FILE* file = NULL;

	while(TRUE)
	{
		retval=recvfrom(sock,recvBuf,0x112,0,(SOCKADDR*)&addrFrom,&len);
		
		if(SOCKET_ERROR == retval)
			break;

		if (recvBuf[0] == 'R')
		{
			char wParam = 'R';
			::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, 0);
		}
		else if (recvBuf[0] == 'D')
		{
			char wParam = 'D';
			::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, 0);
		}
		else if (recvBuf[0] == 'H')
		{
			
			for (i = 1; i <= 0x100 && recvBuf[i] != '\0'; i++)	//前256字节用于存储文件名
				fileName[i-1] = recvBuf[i];
			fileName[i-1] = '\0';
			CString recvMsg;
			nFileSize = atoi(&recvBuf[0x101]);
			recvMsg.Format("收到来自于(%s)的文件:%s\n文件大小:%i字节\n是否接收?",
			inet_ntoa(addrFrom.sin_addr), fileName, nFileSize);
			if (IDOK == AfxMessageBox(recvMsg, MB_OKCANCEL))
			{
				CFileDialog saveDlg(false, NULL, fileName);
				
				if (IDOK == saveDlg.DoModal())
				{
					if (!(file = fopen(saveDlg.GetPathName(), "wb")))
					{
						AfxMessageBox("创建本地文件失败!");
						continue;
					}
					char wParam = 'H';
					::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom);					
				}
				else
				{
					char wParam = 'C';
					::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom);
				}
			}
			else
			{
				char wParam = 'C';
				::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom);
			}

		}
		else if (recvBuf[0] == 'F')
		{
			fwrite(&recvBuf[0x12], 1, 0x100, file);
			char wParam = 'F';
			::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom);
		}
		else if (recvBuf[0] == 'E')
		{
			int bufSize = atoi(&recvBuf[1]);
			fwrite(&recvBuf[0x12], 1, bufSize, file);
			fclose(file);
			char wParam = 'E';
			::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom);
		}
		else
			AfxMessageBox("传送数据过程中出现错误!");
	}
	return (DWORD)NULL;
}

//调出打开对话框查找要发送的文件
void CFilePosterDlg::OnFindFile() 
{
	CFileDialog openFile(true);
	if (IDOK == openFile.DoModal())
	{
		m_filePath = openFile.GetPathName();
		UpdateData(false);
	}
}

//按下发送键,发出文件信息
void CFilePosterDlg::OnOK() 
{
	if (m_posting)
	{
		MessageBox("数据发送中,请稍候再试。");
		return;
	}

	UpdateData();

	if (m_filePath == "")
	{
		MessageBox("请输入要发送的文件路径!");
		return;
	}
	
	if (m_IPAddr.IsBlank())
	{
		MessageBox("请添入接收者的IP地址。");
		return;
	}

	WIN32_FIND_DATA FindFileData;

	if (INVALID_HANDLE_VALUE == FindFirstFile(m_filePath, &FindFileData))
	{
		MessageBox("文件路径错误或文件不存在!\n请重新指定文件路径。");
		return;
	}

	DWORD dwIP;
	m_IPAddr.GetAddress(dwIP);

	SOCKADDR_IN addrTo;
	addrTo.sin_family=AF_INET;
	addrTo.sin_port=htons(6800);
	addrTo.sin_addr.S_un.S_addr=htonl(dwIP);

	char sendBuf[0x112];
	int i;

	sendBuf[0] = 'H';

	for (i = 1; i <= 0x100 && FindFileData.cFileName[i-1] != '\0'; i++)
		sendBuf[i] = FindFileData.cFileName[i-1];
	sendBuf[i] = '\0';

	_itoa(FindFileData.nFileSizeLow, &sendBuf[0x101], 10);
	sendBuf[0x111] = '\0';

	sendto(m_socket, sendBuf, 0x112, 0,
		(SOCKADDR*)&addrTo, sizeof(SOCKADDR));

	if (!(m_file = fopen(m_filePath, "rb")))
	{
		MessageBox("读取文件失败!");
	}
	m_nSend = 0;
	m_nFileSize_s = FindFileData.nFileSizeLow;
	m_progress.SetRange(0, m_nFileSize_s/0x100+1);
	m_posting = true;
}

//消息响应函数,每响应一次发送一段数据
void CFilePosterDlg::OnReadyToRecv(WPARAM wParam,LPARAM lParam)
{
	char sendBuf[0x112];
	DWORD dwIP;
	m_IPAddr.GetAddress(dwIP);

	SOCKADDR_IN addrTo;
	addrTo.sin_family=AF_INET;
	addrTo.sin_port=htons(6800);
	addrTo.sin_addr.S_un.S_addr=htonl(dwIP);

	int nRead;

	switch (*(char*)wParam)
	{
	case 'D':
		MessageBox("对方拒绝接受你发送的文件!");
		fclose(m_file);
		m_posting = false;
		break;
	case 'R':
		nRead = fread(&sendBuf[0x12], 1, 0x100, m_file);

		if (nRead < 0x100)
		{
			sendBuf[0] = 'E';
			_itoa(nRead, &sendBuf[1], 10);
			sendto(m_socket, sendBuf, nRead+0x12, 0,
				(SOCKADDR*)&addrTo, sizeof(SOCKADDR));
			fclose(m_file);
			m_progress.SetPos(m_nFileSize_s/0x100+1);
			m_posting = false;
			m_send = "发送进度:(100%)";
			UpdateData(false);
			MessageBox("发送完毕!");
			m_progress.SetPos(0);
			m_send = "发送进度:";
			UpdateData(false);
		}
		else
		{
			sendBuf[0] = 'F';
			sendto(m_socket, sendBuf, 0x112, 0,
				(SOCKADDR*)&addrTo, sizeof(SOCKADDR));
			m_progress.StepIt();
			m_nSend++;
			m_send.Format("发送进度:(%.1f%%)", (float)m_nSend/(m_nFileSize_s/0x100+1)*100);
			UpdateData(false);
		}
		break;
	case 'H':
		m_progress_r.SetRange(0, nFileSize/0x100+1);
		m_nRecv = 0;
	case 'F':
		sendto(m_socket, "R", 2, 0,
				(SOCKADDR*)lParam, sizeof(SOCKADDR));
		m_progress_r.StepIt();
		m_nRecv++;
		m_recv.Format("接收进度:(%.1f%%)", (float)m_nRecv/(nFileSize/0x100+1)*100);
		UpdateData(false);
		break;
	case 'E':
		m_progress_r.SetPos(nFileSize/0x100+1);
		m_recv = "接收进度:(100%)";
		UpdateData(false);
		MessageBox("接收完毕!");
		m_recv = "接收进度:";
		m_progress_r.SetPos(0);
		UpdateData(false);
		break;
	case 'C':
		sendto(m_socket, "D", 2, 0,
				(SOCKADDR*)lParam, sizeof(SOCKADDR));
		break;
	}
}

void CFilePosterDlg::OnMenuSend() 
{
	OnOK();	
}

void CFilePosterDlg::OnMenuQuit() 
{
	OnCancel();
}

void CFilePosterDlg::OnAbout() 
{
	CAboutDlg dlgAbout;
	dlgAbout.DoModal();	
}

void CFilePosterDlg::OnMenuFind() 
{
	OnFindFile();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -