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

📄 filesend.cpp

📁 vc++6.0开发网络典型应用实例导航 1. 本光盘提供了本书中所有的实例源程序文件。 2. 附录文件夹下是Winsock 函数参考以及错误码列表
💻 CPP
字号:
// FileSend.cpp : implementation file
//

#include "stdafx.h"
#include "Netmsg.h"
#include "FileSend.h"
#include "ContactView.h"
#include "FXFileSend.h"
#include "TransferStatus.h"
#include "ConversationThread.h"
#include "Conversation.h"
#include "StatusThread.h"
#include "NetSocket.h"

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

char *FormatBytes(unsigned long bytes);

//The file send engine

BEGIN_MESSAGE_MAP(CFileSocketThread, CWinThread)
	//{{AFX_MSG_MAP(CPopWndThread)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()




CFileSocketThread::CFileSocketThread(CContact *pContact, bool bSend, char *szFileName, int nPort, unsigned long lFileLen)
{
	Sending = bSend;
	Finished = false;
	hFile = NULL;
	Sock = NULL;
	FileName = szFileName;
	RemotePort = nPort;
	FileLen = lFileLen;
	SendSock = NULL;
	RecvSock = NULL;
	Contact = pContact;
	Transfered = 0L;
	LastTransfered = 0L;
	StatusDlg = NULL;
	StatusConv = NULL;
}

CFileSocketThread::~CFileSocketThread()
{
}

BOOL CFileSocketThread::InitInstance()
{
	HWND ParentWnd;
	if (Contact->IsConvWindowOpen())	//file transfer can be displayed in either a seperate dialog or 
	{									//in the conversation window depending if it is active or not.
		ParentWnd = Contact->pThread->Conv->GetSafeHwnd();
		StatusConv = Contact->pThread->Conv;
		DlgMode = 0;
	}
	else
	{
		CStatusThread *StatusThread = new CStatusThread();
		StatusThread->CreateThread();

		while (!StatusThread->Init)
		{
			Sleep(1); //synchronise threads
		}

		StatusDlg = StatusThread->Dialog;
		ParentWnd = StatusDlg->GetSafeHwnd();
		DlgMode = 1;
	}

	if (Sending)
		strcpy(szFile, "*.*");
	else
		strcpy(szFile, FileName);

	if (DlgMode)
	{
		StatusDlg->SetStatus("Choosing local file...");
	}
	else
	{
		//nothing
	}

	if ((!Sending) || (Sending && !FileName))
	{
		if (!GetFileName(Sending, ParentWnd, szFile))
		{
			::SendMessage(GetApp()->View->GetSafeHwnd(), WM_CANCELXFER, 0, (LPARAM) Contact);
			if (DlgMode) 
			{
				StatusDlg->Remove();
			}
			else
			{
				StatusConv->Remove();
			}
			PostThreadMessage(WM_QUIT, 0, 0);
			return TRUE;
		}
	}
	else
	{
		strcpy(szFile, FileName);
	}

	if (Sending)
	{
		XFER *Xfer = new XFER; //remember to delete
		unsigned long dwUpper, dwLower;

		hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);

		if (!hFile)
		{
			MessageBox(ParentWnd, "A problem occured when attempting to open this file", "Send error", MB_OK|MB_ICONSTOP);
			if (DlgMode)
			{
				StatusDlg->Remove();
			}
			else
			{
				StatusConv->Remove();
			}
			delete Xfer;
			PostThreadMessage(WM_QUIT, 0, 0);
			return TRUE;
		}

		dwLower = GetFileSize(hFile, &dwUpper);

		if (dwUpper || !dwLower)
		{
			MessageBox(ParentWnd, "A problem with the file size is preventing this program from sending the file", "Send error", MB_OK|MB_ICONSTOP);
			if (DlgMode)
			{
				StatusDlg->Remove();
			}
			else
			{
				StatusConv->Remove();
			}
			delete Xfer;
			PostThreadMessage(WM_QUIT, 0, 0);
			return TRUE;
		}

		Xfer->Contact = Contact;
		Xfer->filelen = dwLower;
		Xfer->port = GetFreePort();
		nopath(Xfer->filename, szFile);

		FileLen = dwLower;
		RemotePort = Xfer->port;

		if (DlgMode)
		{
			StatusDlg->InitStatus(this, Contact, Sending, szFile);
		}
		else
		{
			if (!StatusConv->InitStatus(this, NULL, Sending, szFile))
				MessageBox(NULL, "An internal error has occurred (CConversation::InitStatus() Failed)", "Error", MB_ICONSTOP | MB_OK);
		}

		::SendMessage(GetApp()->View->GetSafeHwnd(), WM_REQUESTXFER, 0, (LPARAM) Xfer);

		if (DlgMode)
		{
			StatusDlg->SetStatus("Waiting for remote user to accept...");
		}
		else
		{
			StatusConv->SetStatus("Waiting for remote user to accept...");
		}

		Sock = new CFXListen(this);

		if (!Sock->Create(RemotePort))
		{
			char buf[512];
			sprintf(buf, "Unable to port %d. transfer will not take place.", RemotePort);
			MessageBox(ParentWnd, buf, "File transfer", MB_OK|MB_ICONSTOP);
			if (DlgMode)
			{
				StatusDlg->Remove();
			}
			else
			{
				StatusConv->Remove();
			}
			PostThreadMessage(WM_QUIT, 0, 0);
			return TRUE;
		}
		else
			Sock->Listen();
	}

	else
	{
		hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);

		if (!hFile)
		{
			MessageBox(ParentWnd, "A problem occured when attempting to save this file", "Send error", MB_OK|MB_ICONSTOP);
			if (DlgMode)
			{
				StatusDlg->Remove();
			}
			else
			{
				StatusConv->Remove();
			}
			PostThreadMessage(WM_QUIT, 0, 0);
			return TRUE;
		}

		RecvSock = new CFXFileRecv(this, hFile, FileLen);

		RecvSock->Create();

		if (!RecvSock->Connect(Contact->GetHostName().Get(), RemotePort))
		{
			MessageBox(ParentWnd, "Unable to connect to remote machine. transfer will not take place", "File transfer", MB_OK|MB_ICONSTOP);
			if (DlgMode)
			{
				StatusDlg->Remove();
			}
			else
			{
				StatusConv->Remove();
			}
			PostThreadMessage(WM_QUIT, 0, 0);
			return TRUE;

		}
		else
		{
			if (DlgMode)
				StatusDlg->InitStatus(this, Contact, Sending, szFile);
			else
				StatusConv->InitStatus(this, NULL, Sending, szFile);
				
			TransferStarted();
		}
	}
	return TRUE;
}

int CFileSocketThread::GetFreePort()
{
	int Baseport = 8401, port;
	for (port = Baseport; port < 9000; port++)
	{
		POSITION pos;
		pos = GetApp()->View->List.GetHeadPosition();
		while (pos)
		{
			CContact *pContact = GetApp()->View->List.GetNext(pos);
			if (pContact->IsTransfering() && pContact != Contact)
			{
				port++;
				continue;
			}
		}
		break;
	}
	return port;
}

void CFileSocketThread::TransferAccepted()
{
	if (DlgMode)
	{
		if (!::IsWindow(StatusDlg->m_hWnd)) return;
		StatusDlg->SetStatus("Remote user is choosing save file path...");
	}
	else
	{
		StatusConv->SetStatus("Remote user is choosing save file path...");
	}
}

void CFileSocketThread::TransferStarted()
{
	LastUpdated = 0;
	LastUpdated2 = 0;

	if (RecvSock)
		if (RecvSock->Stop)
			return;

	if (SendSock)
		if (SendSock->Stop)
			return;

	if (DlgMode)
	{
		StatusDlg->SetStatus("Transfer in progress");
	}
	else
	{
		char buf[512], buf2[512];;
		nopath(buf2, szFile);
		sprintf(buf, "%s: %s", Sending ? "Sending" : "Receiving", buf2);
		StatusConv->SetStatus(buf);
	}
}

void CFileSocketThread::TransferComplete()
{
	Finished = true;
	if (hFile) 
	{	
		CloseHandle(hFile);
		hFile = NULL;
	}

	if (RecvSock)
		if (RecvSock->Stop)
			return;

	if (SendSock)
		if (SendSock->Stop)
			return;

	if (DlgMode)
	{
		StatusDlg->SetStatus("Transfer complete!");
		StatusDlg->SetPercent(100);
		StatusDlg->Ended();
	}
	else
	{
		StatusConv->SetStatus("Transfer complete!");
		StatusConv->SetPercent(100);
		StatusConv->Ended();
	}
}

void CFileSocketThread::TransferFailed()
{
	Finished = true;
	if (hFile) 
	{	
		CloseHandle(hFile);
		hFile = NULL;
	}

	if (RecvSock)
		if (RecvSock->Stop)
			return;

	if (SendSock)
		if (SendSock->Stop)
			return;

	if (DlgMode)
	{
		if (!::IsWindow(StatusDlg->m_hWnd)) return;
		StatusDlg->SetStatus("Transfer failed");
		StatusDlg->Ended();
	}
	else
	{
		StatusConv->SetStatus("Transfer failed");
		StatusConv->Ended();
	}
}

void CFileSocketThread::UpdateTransfered(int nBytes)
{
	if (RecvSock)
		if (RecvSock->Stop)
			return;

	if (SendSock)
		if (SendSock->Stop)
			return;

	Transfered += nBytes;
	if ((GetTickCount() - LastUpdated) > 1000)
	{
		if (DlgMode)
		{	
			StatusDlg->SetStats(Transfered, Transfered - LastTransfered);
		}
		else
		{
			StatusConv->SetStats(Transfered, Transfered - LastTransfered);
		}
		LastUpdated = GetTickCount();
		LastTransfered = Transfered;
	}
	if (GetTickCount() - LastUpdated2 > 50)
	{
		float fldone = ((float)Transfered / (float)FileLen) * 100;

		if (DlgMode)
		{
			StatusDlg->SetPercent((int) fldone);
		}
		else
		{
			StatusConv->SetPercent((int) fldone);
		}
		LastUpdated2 = GetTickCount();
	}
}


bool CFileSocketThread::GetFileName(bool bSending, HWND hWndOwner, char *FileName)
{
	char file[1024];
	bool bResult;
	strncpy(file, FileName, sizeof(file));
	OPENFILENAME ofn;
	ZeroMemory(&ofn, sizeof(OPENFILENAME));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hWndOwner;
	ofn.lpstrFile = file;
	ofn.nMaxFile = sizeof(file);
	ofn.lpstrFilter = "All Files (*.*)\0*.*\0";
	ofn.nFilterIndex = 1;
	ofn.lpstrFileTitle = NULL;
	ofn.nMaxFileTitle = 0;
	ofn.lpstrInitialDir = NULL;
	ofn.Flags = bSending ? OFN_FILEMUSTEXIST : OFN_OVERWRITEPROMPT;
	
	if (Sending)
		bResult = GetOpenFileName(&ofn) ? true : false;
	else
		bResult = GetSaveFileName(&ofn) ? true : false;
	
	if (bResult)
	{
		strcpy(FileName, ofn.lpstrFile);
		return true;
	}
	else
	return false;
}

void CFileSocketThread::Kill()
{
	if (Sending)
	{
		if (SendSock)
		{	//since sock threads are going hard nut the only way to stop them is to
			//set a boolean that it checks every cycle to false from another thread 
			SendSock->Stop = true;
		}
	}
	else
	{
		if (RecvSock)
		{
			RecvSock->Stop = true;
		}
	}
	if (!Finished) GetApp()->View->SendMessage(WM_CANCELXFER, 0, (LPARAM) Contact);
	PostThreadMessage(WM_QUIT, 0, 0);
	return;
}

int CFileSocketThread::ExitInstance()
{
	if (hFile) 
	{	
		CloseHandle(hFile);
		hFile = NULL;
	}
	if (Sending)
	{
		delete SendSock;
		if (Sock)
		delete Sock;	
	}
	else
	{
		delete RecvSock;
	}
	Contact->Flags &= ~CFL_TRANSFER;
	return CWinThread::ExitInstance();
}

/////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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