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

📄 filetranscltview.cpp

📁 文件传送协议的服务器端和客户端源码
💻 CPP
字号:
// FileTransCltView.cpp : implementation of the CFileTransCltView class
//

#include "stdafx.h"
#include "FileTransClt.h"

#include "FileTransCltDoc.h"
#include "FileTransCltView.h"

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

/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView

typedef struct{          //pakcet for socket
	char packetType;     //r:request rootdriver,d:directory f:file D:data
	unsigned int length;
	char content[2000];
}DATA_PACKET;

 char* pDrives;
 CString arrFiles[200];
 CString savePath;
 long fSize=0l,recvFSize=0l;
 CString strIP;
 bool thrFlag=false;

 CCriticalSection critSection;

IMPLEMENT_DYNCREATE(CFileTransCltView, CFormView)

BEGIN_MESSAGE_MAP(CFileTransCltView, CFormView)
	//{{AFX_MSG_MAP(CFileTransCltView)
	ON_BN_CLICKED(IDC_CONNECT, OnConnect)
	ON_NOTIFY(NM_DBLCLK, IDC_FILEBROWSE, OnDblclkFilebrowse)
	ON_NOTIFY(TVN_SELCHANGED, IDC_FILEBROWSE, OnSelchangedFilebrowse)
	ON_NOTIFY(NM_RCLICK, IDC_FILEBROWSE, OnRclickFilebrowse)
	ON_COMMAND(IDC_SETPARAM, OnSetparam)
	ON_COMMAND(ID_DOWNLOAD, OnDownload)
	ON_COMMAND(ID_SAVEAS, OnSaveas)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView construction/destruction

CFileTransCltView::CFileTransCltView()
	: CFormView(CFileTransCltView::IDD)
{
	//{{AFX_DATA_INIT(CFileTransCltView)
	m_fullPath = _T("");
	//}}AFX_DATA_INIT
	// TODO: add construction code here

	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD( 2, 2 );
	
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		return;
	}
	
	if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 2 ) {
		WSACleanup( );
		return; 
	}

}

CFileTransCltView::~CFileTransCltView()
{
	//delete[] pDrives;  //It will occur an assert failed!
}

void CFileTransCltView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFileTransCltView)
	DDX_Control(pDX, IDC_FILEBROWSE, m_FileTreeBrowse);
	DDX_Control(pDX, IDC_IPADDRESS, m_IPAddress);
	DDX_Text(pDX, IDC_FULLPATH, m_fullPath);
	DDX_Control(pDX, IDC_PROGCTRL, m_progCtrl);
	//}}AFX_DATA_MAP
}

BOOL CFileTransCltView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CFormView::PreCreateWindow(cs);
}

void CFileTransCltView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();

	m_IPAddress.SetWindowText("127.0.0.1");
	hCurrent=m_FileTreeBrowse.InsertItem("我的电脑",0,0,TVI_ROOT);

}

/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView printing

BOOL CFileTransCltView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CFileTransCltView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CFileTransCltView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

void CFileTransCltView::OnPrint(CDC* pDC, CPrintInfo* /*pInfo*/)
{
	// TODO: add customized printing code here
}

/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView diagnostics

#ifdef _DEBUG
void CFileTransCltView::AssertValid() const
{
	CFormView::AssertValid();
}

void CFileTransCltView::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}

CFileTransCltDoc* CFileTransCltView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFileTransCltDoc)));
	return (CFileTransCltDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView message handlers

void CFileTransCltView::OnConnect() 
{
	// TODO: Add your control notification handler code here
	DWORD dwAddress;
	m_IPAddress.GetAddress(dwAddress);
	strIP.Format("%d.%d.%d.%d",   
		HIBYTE(HIWORD(dwAddress)),   
		LOBYTE(HIWORD(dwAddress)),   
		HIBYTE(LOWORD(dwAddress)),   
		LOBYTE(LOWORD(dwAddress))   
		);   

	DWORD dwThread;
	DATA_PACKET requestPacket;
	requestPacket.packetType='r';

	::CreateThread(NULL,0,ThreadRequest,(LPVOID)&requestPacket,0,&dwThread); 
		
	m_fullPath="Connect succedd,and the root diretory is ready.";
	UpdateData(false);

}

DWORD WINAPI CFileTransCltView::ThreadRequest(LPVOID lpParameter)
{
	DATA_PACKET requestPacket=*(DATA_PACKET*)lpParameter;

	SOCKET socket=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	sockaddr_in sin;
	sin.sin_addr.S_un.S_addr=inet_addr(strIP);
	sin.sin_family=AF_INET;
	sin.sin_port=htons(1032);

	if(::connect(socket,(sockaddr*)&sin,sizeof(sin))!=0)
	{
		AfxMessageBox("Request failure!");
		return 0;
	}

	int thrInfo;
	if( requestPacket.packetType=='D' )       //save download thead infomation
	{
		thrInfo=requestPacket.length;
		thrFlag=true;
	}
	
	::send( socket,(char*)&requestPacket,sizeof(requestPacket),0 );
	memset( requestPacket.content,0,sizeof(requestPacket.content) );

	if( ::recv(socket,(char*)&requestPacket,sizeof(requestPacket),0) )
	{
		if( requestPacket.packetType=='r' )
		{
			int szBuffer=requestPacket.length;
			pDrives=new char[2000];        //Make sure that allocate memery!
			memcpy(pDrives,requestPacket.content,szBuffer);  //Make sure that use memcpy()
		}


		if(requestPacket.packetType=='d' )
		{
			pDrives=new char[2000];
			Memcpy( pDrives,requestPacket.content,sizeof(requestPacket.content) );  /* 2000 will take an error ?????*/
			//char's pointer to CString Array
			int i=0,j=0;
			//Sleep(50);
			//critSection.Lock();
  			while( i<requestPacket.length ) 
			{
				for(int k=0; pDrives[i]!='|' && i<requestPacket.length ; k++,i++ )				
					arrFiles[j].Insert(k,pDrives[i]);
			
				i++;
				j++;
			}
			//critSection.Unlock(); 
			return 0;
		}

		if( requestPacket.packetType=='f' )
			fSize=requestPacket.length;
	
		//Write file
		if( requestPacket.packetType=='D' )
		{
			//memset( pDrives,0,2000 );
			Memcpy( pDrives,requestPacket.content,sizeof(requestPacket.content) );
			FillInFile( socket,thrInfo,requestPacket.length,pDrives);
		}

	}
	::closesocket(socket);

	//pDrives=requestPacket.content;  error
	return 0;
}

void CFileTransCltView::OnDblclkFilebrowse(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here

	m_fullPath.Delete(0,8);

	//Fill Tree Root with Logical drives
	if( m_fullPath==""&&pDrives!=NULL )
	{
		while( *pDrives )
		{
			m_FileTreeBrowse.InsertItem( pDrives,hCurrent,TVI_LAST );
			pDrives += strlen( pDrives ) + 1;
		}
	}

	//request sub directory or files' name
	if(m_fullPath!=""&&m_fullPath.Find('.')==-1)
	{
		m_fullPath.Delete(0,1);   //strlen("我的电脑\") equal to 9 BYTE	
		//m_fullPath+='\0';
		//MessageBox(m_fullPath);

		DATA_PACKET dataPacket;
		dataPacket.packetType='d';
		dataPacket.length=m_fullPath.GetLength();
		memcpy( dataPacket.content,m_fullPath,strlen(m_fullPath) );

		::CreateThread(NULL,0,ThreadRequest,(LPVOID)&dataPacket,0,0);
		while(arrFiles[0]=="")
			Sleep(30);
		CFileTransCltView::FillTree();
	}
   
	//DownLoad file which was clicked doubly 
	if(m_fullPath.Find('.')!=-1)
	{
		m_fullPath.Delete(0,1);
		m_fullPath.Delete(2,1);
        CFileTransCltView::DownloadFile(m_fullPath);
	}
}


void CFileTransCltView::OnSelchangedFilebrowse(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	
	hCurrent=pNMTreeView->itemNew.hItem;
	m_fullPath = m_FileTreeBrowse.GetFullPath( hCurrent );
	UpdateData(false);

	*pResult = 0;
}

void CFileTransCltView::FillTree()
{
	int i=0;
	while(i<200&&arrFiles[i]!="")
	{
		m_FileTreeBrowse.InsertItem( arrFiles[i],hCurrent,TVI_LAST );
		i++;
	}

	//Clear the globle parameter of arrFile[i]
	//memcpy( arrFiles,0,sizeof(arrFiles) );    //disable
	for(int j=0;j<i;j++)
		arrFiles[j]="";  
}



void CFileTransCltView::OnRclickFilebrowse(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	/* First of all, It should judge the current path,if it's a drive or a directory,disable
		the popup menu.Or else,it's a file path,enable the popup menu.
		The problem here is that popup menu can set the item in tree focus,but not change the 
		item selected.In other words, the focus has been changed,but the selected item and
		current path haven't been changed. Who know this, contact me please. Email:
		tidge1982@yahoo.com.cn	Thanks!		*/

	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	hCurrent=pNMTreeView->itemNew.hItem;
	m_FileTreeBrowse.SetItemState( hCurrent,TVIS_SELECTED,TVIS_SELECTED );

	if(m_fullPath.Find('.')!=-1)
	{
		
		CPoint point;
		GetCursorPos(&point);
		
		if (point.x == -1 && point.y == -1)
		{
			//keystroke invocation
			CRect rect;
			GetClientRect(rect);
			ClientToScreen(rect);
			
			point = rect.TopLeft();
			point.Offset(5, 5);
		}
		
		CMenu menu;
		VERIFY(menu.LoadMenu(CG_IDR_POPUP_EXTN_TREE_CTRL));
		
		CMenu* pPopup = menu.GetSubMenu(0);
		ASSERT(pPopup != NULL);
		CWnd* pWndPopupOwner = this;
		
		while (pWndPopupOwner->GetStyle() & WS_CHILD)
			pWndPopupOwner = pWndPopupOwner->GetParent();
		
		pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
			pWndPopupOwner);
	}
	
	*pResult = 0;
}

void CFileTransCltView::OnSetparam() 
{
	// TODO: Add your command handler code here
	CSetParam setParam;
	setParam.DoModal();
}

void CFileTransCltView::DownloadFile(CString fPath)
{
	//Requet file size
	DATA_PACKET dataPacket;
	dataPacket.packetType='f';
	dataPacket.length=strlen(m_fullPath);
	
	memset( dataPacket.content,0,sizeof(dataPacket.content) );
	memcpy( dataPacket.content,m_fullPath,strlen(m_fullPath) );
	::CreateThread(NULL,0,ThreadRequest,(LPVOID)&dataPacket,0,0);   // thread for request file size
	while(fSize==0)
		Sleep(30);                            
	
	//download
	
	CString subPath = m_FileTreeBrowse.GetSubPath(fPath); 
	CString tempPath = setParam.GetDefSavePath();
    tempPath += '\\'+ subPath;
	savePath.Format( "%s",tempPath );	  // 'savePath' is a global parameter

	dataPacket.packetType='D';	
	memcpy( dataPacket.content,fPath,strlen(fPath) );   // fPath is file path in server

	int i = setParam.GetDefThrTotal();        // Download threads in total
	for(int j=1;j<=i;j++)
	{
		dataPacket.length=j*100+i;       // download thread index
		::CreateThread(NULL,0,ThreadRequest,(LPVOID)&dataPacket,0,0); 
		while( !thrFlag )                // make sure the thread has been created.This is very important!!!
			Sleep(50);	
		thrFlag = false;
	}

	m_progCtrl.SetRange( 0,100 );
	m_progCtrl.SetPos( 0 );
	SetTimer( 1,20,NULL );     // Calculate and display the progress in OnTimer();
	                            // use sleep() will block the UI and no efficency!
	
}

void CFileTransCltView::FillInFile(SOCKET socket,int thrInfo,int packIndex,char* pPackCont)
{
	int thrIndex = thrInfo/100;
	int thrTotal = thrInfo-thrIndex*100;

	int thrLength = fSize/thrTotal;
	int bPoint = (thrIndex-1)*thrLength;
	if( thrIndex == thrTotal )
		thrLength = fSize-bPoint;

	FILE *file;
	if( (file  = fopen( savePath, "ab" )) == NULL )
       AfxMessageBox( "Open file occur an error\n" );
	//fseek(file,bPoint,SEEK_SET);

	int packTotal = thrLength/2000 +1;
	int subTotal = packTotal;
	DATA_PACKET dPacket;
	while( subTotal>0 )	
	{
		critSection.Lock(5000);
		fseek( file,bPoint+(packIndex-1)*2000,SEEK_SET );

		if( packIndex == packTotal )    //the last packet in thread,data maybe less than 2000B
		{
			int fLength = thrLength-(packTotal-1)*2000;
			int errorcode=fwrite( pPackCont,1,fLength,file );
			fflush(file);
			recvFSize+=fLength;
		}
		else
		{
			fwrite( pPackCont,sizeof(char),2000,file );
			fflush(file);
			recvFSize+=2000;
		}

		critSection.Unlock();
		subTotal--;
		if( subTotal>0 )
		{
			if( recv( socket,(char*)&dPacket,sizeof(dPacket),0 ) != 0 )
			{
				packIndex = dPacket.length;
				Memcpy( pPackCont,dPacket.content,sizeof(dPacket.content) );
			}
		}
		else 
		{
			if( recvFSize == fSize )
				fclose(file);
			return;
		}
		
	}
}

void CFileTransCltView::Memcpy(char *dest, char *sour, unsigned int num)
{
	// Just for test.
	// Actually,There is no need 

	for(int i=0;i<num;i++ )
		dest[i]=sour[i];
}

void CFileTransCltView::OnDownload() 
{
	// TODO: Add your command handler code here
	AfxMessageBox("disable!"); 
}

void CFileTransCltView::OnSaveas() 
{
	// TODO: Add your command handler code here
	AfxMessageBox("disable!"); 
}

void CFileTransCltView::OnTimer(UINT nIDEvent) 
{
	// TODO: Calculate and display the download progress ;

	if( fSize > recvFSize )
	{
		float progress = (float)recvFSize/(float)fSize*100 ;
		m_fullPath.Format("Current progress %f",progress);
		UpdateData(false);

		m_progCtrl.SetPos( (int)progress );
	}
	else
	{
		recvFSize = 0;               // clear for next time
		m_progCtrl.SetPos( 100 );    // during the time, Maybe file has received all,but progress bar no time to do it.
		m_fullPath.Format( "All are receive! The file has been save in %s.",savePath );
		UpdateData(false);
		KillTimer( 1 );
	}

	CFormView::OnTimer(nIDEvent);
}

⌨️ 快捷键说明

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