www.pudn.com > UDP文件传输.rar > ZsP2PBlock.h


// ZsP2PBlock.h: interface for the CZsP2pBlock class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#if !defined(AFX_HP2PBLOCK_H__B3D1AFBD_2E56_409E_AB2B_50952DC3FF02__INCLUDED_) 
#define AFX_HP2PBLOCK_H__B3D1AFBD_2E56_409E_AB2B_50952DC3FF02__INCLUDED_ 
 
#if _MSC_VER > 1000 
#pragma once 
#endif // _MSC_VER > 1000 
////////////////////////////////////////////////////////////////////////////// 
 
 
//文件名		: ZsP2PBlock.h 
 
//功能			: 中搜UDP文件传输数据发送接收程序 
 
//创建			: 2004.11.14 
 
//修改日期		: 2004.11.14 
 
//作者			: 韩国静 
// 
 
#include "HUDPCanal.h" 
#include "../public/zs_p2pfilecmd.h" 
#include "ZsP2pEventHandle.h" 
#include "HThread.h" 
 
#ifdef _DEBUG 
#include "HFile.h" 
inline void P2P_WriteLog(char *filename,char *info) 
{ 
	HFile file; 
	if(file.OpenForAppend(filename)) 
	{ 
		file.Write(info,strlen(info)); 
		file.Close(); 
	} 
} 
#endif 
 
#define TIME_OUT_UNIT 1500 
 
#ifndef P2P_UDP_KERNEL 
#define P2P_UDP_KERNEL 1 
#endif 
 
class CZsP2pBlock:public IThreadRun  
{ 
//	bool m_ThreadDeleteMe; 
 
	typedef enum{ 
	FILE_ACT_ACCEPT, 
	FILE_ACT_REFUSE, 
	FILE_ACT_WAIT, 
	}E_FILE_ACT; 
 
	typedef struct OBJECTINFO 
	{ 
		UI_FILEINFO BaseInfo; 
		UNI_DWORD   dwSvrIp; 
		UNI_WORD    wPort; 
		H_CANAL_ID   myCanalId;	//本此传输使用的通道ID,通道ID由服务器分配 
		HCANAL		hsvr;		//本此传输与服务器的通道(每次传输两方可能选择与上次不同的服务器共同登录) 
 
 
		UNI_DWORD	dwFileOffset; 
		E_FILE_ACT	eAct;			//用户采取的动作,也是文件传输状态如:接受,取消,拒绝 
		UNI_BOOL	bResult;		//舆传输结果成功与否,一个给上层看的标志 
		HCANAL		hfrom;			//传输本文件占用的通道 
		UNI_DWORD	dwTickCount;	//最后一次对命令的响应时间 
		UNI_DWORD	dwTimeOutCount; 
		UNI_DWORD	dwStreamPackCount; 
		UNI_DWORD	dwTaskMaxPackSize; 
		PUDPFILE_CMD pLastCmd;//最后一次命令 
	}*POBJECTINFO; 
 
	class IEnumTask 
	{ 
	public : 
		virtual UNI_BOOL TreadItem(POBJECTINFO pNode,UNI_DWORD dwTick)=0; 
	};	 
	class UDPtaskList 
	{ 
		typedef CHList UDPFileInfoList; 
		UDPFileInfoList m_Files; 
		CHMutex			m_Mutex; 
		 
	public: 
		UNI_DWORD GetCount() 
		{ 
			UNI_DWORD dwCount; 
			m_Mutex.Lock(); 
			dwCount=m_Files.GetCount(); 
			m_Mutex.UnLock(); 
			return dwCount; 
		} 
		OBJECTINFO *FindFile(UNI_DWORD fileId,char *sendName) 
		{ 
			OBJECTINFO *pfile,** pNode; 
			UDPFileInfoList::HLISTPOSTION pos; 
			pfile=UNI_NULL; 
			m_Mutex.Lock(); 
			if(pos=m_Files.MoveToBegin()) 
			{ 
				while(pNode=m_Files.MoveToNext(pos)) 
				{ 
					pfile=*pNode; 
					if(pfile->BaseInfo.dwFileID ==fileId && strcmp(sendName,pfile->BaseInfo.sendName)==0) 
					{ 
						m_Files.Remove(pNode); 
						break; 
					} 
					pfile=UNI_NULL; 
				} 
			} 
			m_Mutex.UnLock(); 
			return pfile; 
		} 
		UNI_BOOL AddTail(OBJECTINFO *pfile) 
		{ 
			OBJECTINFO **pNode; 
			pNode=UNI_NULL; 
			m_Mutex.Lock(); 
			if(pNode=m_Files.AddTail()) 
			{ 
				*pNode=pfile; 
			} 
			m_Mutex.UnLock(); 
			return pNode?UNI_TRUE:UNI_FALSE; 
		} 
		void EnumItem(IEnumTask *pEnumTask,UNI_DWORD dwTick) 
		{ 
			OBJECTINFO **pNode; 
			UDPFileInfoList::HLISTPOSTION pos; 
			m_Mutex.Lock(); 
			if(pos=m_Files.MoveToBegin()) 
			{ 
				while(pNode=m_Files.MoveToNext(pos)) 
				{ 
					if(pEnumTask->TreadItem(*pNode,dwTick)==UNI_TRUE) 
					{ 
						m_Files.Remove(pNode); 
					} 
				} 
			} 
			m_Mutex.UnLock(); 
		} 
		void Empty() 
		{ 
			m_Mutex.Lock(); 
			m_Files.EmptyAll(); 
			m_Mutex.UnLock(); 
		} 
	public: 
	}; 
	class X_SendTimeOut:public IEnumTask 
	{ 
		UNI_BOOL TreadItem(POBJECTINFO pNode,UNI_DWORD dwTick) 
		{ 
			if(pNode->pLastCmd!=UNI_NULL && 
//				pNode->hfrom==pNode->hsvr&&//取消时可能丢包。 
				(UNI_DWORD)(dwTick-pNode->dwTickCount) >TIME_OUT_UNIT) 
			{ 
				return m_pThis->SendOnAckTimeOut(pNode); 
			} 
			return UNI_FALSE; 
		} 
	public: 
		CZsP2pBlock *m_pThis; 
	}m_sendTimeOut; 
	class X_RecvTimeOut:public IEnumTask 
	{ 
		UNI_BOOL TreadItem(POBJECTINFO pNode,UNI_DWORD dwTick) 
		{ 
			 
			if(pNode->pLastCmd!=UNI_NULL &&		 
				(UNI_DWORD)(dwTick-pNode->dwTickCount) >TIME_OUT_UNIT) 
			{ 
				return m_pThis->RecvOnAckTimeOut(pNode);; 
			} 
			return UNI_FALSE; 
		} 
	public: 
		CZsP2pBlock *m_pThis; 
	}m_recvTimeOut; 
	class X_Cancel:public IEnumTask 
	{ 
		UNI_BOOL TreadItem(POBJECTINFO pNode,UNI_DWORD dwTick) 
		{ 
			if(pNode->BaseInfo.dwFileSize)//SEND 
			{ 
				m_pThis->UserCancelSend(pNode->BaseInfo.dwFileID,pNode->BaseInfo.sendName,UNI_TRUE); 
			} 
			else 
			{ 
				m_pThis->UserCancelRecv(pNode->BaseInfo.dwFileID,pNode->BaseInfo.sendName,UNI_TRUE); 
			} 
			delete pNode; 
			return UNI_TRUE; 
		} 
	public: 
		CZsP2pBlock *m_pThis; 
	}m_Cancel; 
	class X_Delete:public IEnumTask 
	{ 
		UNI_BOOL TreadItem(POBJECTINFO pNode,UNI_DWORD dwTick) 
		{ 
			if(pNode->BaseInfo.pExtra) 
			{ 
				m_pThis->m_pEvent->UI_UnInitialize(&pNode->BaseInfo,pNode->BaseInfo.pExtra); 
			} 
			m_pThis->DeleteFileInfo(pNode); 
			return UNI_TRUE; 
		} 
	public: 
		CZsP2pBlock *m_pThis; 
	}m_Delete; 
	class X_Canals:public HUDPCanal 
	{ 
		virtual UNI_BOOL  AnalyzieCanalID(void *cmd,UNI_DWORD dwCmdSize,UNI_DWORD realip,UNI_WORD realport,H_CANAL_ID &canalId) 
		{ 
			PUDPFILE_CMD pcmd=(PUDPFILE_CMD)cmd; 
#ifdef _DEBUG 
			printf("AnalyzieCanalID recv from %s,%d!",HSocket::getipstr(realip),realport); 
#endif		 
			if(dwCmdSize>=sizeof(pcmd->head) && pcmd!=UNI_NULL) 
			{ 
				/* 
#ifdef _DEBUG 
			printf("\n\tCMD=%d type=%d",pcmd->head.cmd,pcmd->head.type); 
#endif	 
			*/ 
				switch(pcmd->head.cmd) 
				{ 
				case UDP_SVR_FILE_WAIT: 
				case UDP_SVR_FILE_NO: 
				case UDP_SVR_FILE_ACK: 
				case UDP_SVR_FILE_REQ: 
				case UDP_SVR_ACK: 
					if(pcmd->head.type!=UDP_FILE_PROXY) 
					{ 
						canalId.dwIP=realip; 
						canalId.wPORT=realport; 
						break; 
					}//如果是服务器转发仍用转发前的通道号 
				default: 
					canalId.dwIP=pcmd->head.out_ip; 
					canalId.wPORT=pcmd->head.out_port; 
					break; 
				} 
#ifdef _HDEBUG 
				printf("\tCANALID=(%s,%d)\r\n",HSocket::getipstr(canalId.dwIP),canalId.wPORT); 
#endif				 
				return UNI_TRUE; 
			} 
#ifdef _HDEBUG 
				printf("\tCANALID=UNI_FALSE\r\n"); 
#endif				 
			return UNI_FALSE; 
		} 
	public: 
		 
		void ContinueConnect(HCANAL hcanal) 
		{ 
			UDPFILE_CMD cmd; 
			H_CANAL_ID id; 
			id.dwIP=0; 
			id.wPORT=0; 
		//	if(pP2p->m_CanalId.wPORT!=pP2p->m_MyPort//说明自己不在公网上 
		//		||hcanal==pP2p->m_hSvr) 
			{ 
				pP2p->InitializeCmd(&cmd.head,0,0,0,"******",UDP_CLIENT_HERE,id); 
				 
				HUDPCanal::Send(hcanal,&cmd,sizeof(cmd.head)); 
#ifdef _HDEBUG 
			//	if(hcanal==pP2p->m_hSvr) 
			//	{ 
			//		printf("#######re send HERE TO SVR\r\n"); 
			//	} 
			//	else  
				{ 
					printf("####### send HERE TO other client\r\n"); 
				} 
#endif 
 
			} 
		//	else 
		//		HUDPCanal::ContinueConnect(hcanal); 
		} 
 
	public: 
		CZsP2pBlock * pP2p; 
 
	}m_UDPCanal; 
 
	void ContinueConnect(HCANAL hcanal,H_CANAL_ID &id) 
	{ 
		UDPFILE_CMD cmd; 
		InitializeCmd(&cmd.head,0,0,0,"******",UDP_CLIENT_HERE,id); 
		m_UDPCanal.Send(hcanal,&cmd,sizeof(cmd.head)); 
	} 
	UDPtaskList		m_recvFiles; 
	UDPtaskList		m_SendFiles; 
	UDPtaskList		m_CancelFiles; 
	 
//	HCANAL			m_hSvr; 
	char			m_MyName[MAX_NAME]; 
	char			m_MyPassWord[MAX_NAME]; 
	UNI_DWORD		m_MyIp; 
	UNI_WORD		m_MyPort; 
//	H_CANAL_ID		m_CanalId; 
	CHThread		m_WorkThread; 
	UNI_BOOL		m_bRuning; 
	ZsP2pEventHandle *		m_pEvent; 
	//////////////////////////////////// 
	//////////////////////////////////// 
 
	void InitializeCmd(FILE_CMD *pcmd,UNI_DWORD dwFileID, 
		UNI_DWORD dwFileSize,UNI_DWORD dwOffset,char *sendName,UNI_WORD cmd,H_CANAL_ID &canalid) 
	{ 
#define _htonl(arg) arg 
#define _htons(arg) arg 
 
		memset(pcmd,0,sizeof(*pcmd)); 
		pcmd->trans_id=_htonl(dwFileID); 
		pcmd->stream_size =_htonl(dwFileSize); 
		pcmd->pack_id=_htonl(dwOffset); 
		pcmd->cmd=_htons(cmd); 
		strncpy(pcmd->user_name ,this->m_MyName,sizeof(pcmd->user_name)); 
		strncpy(pcmd->append_str,sendName,sizeof(pcmd->append_str)); 
		pcmd->use_ip=m_MyIp; 
		pcmd->use_port=_htons(m_MyPort); 
		pcmd->out_ip=canalid.dwIP; 
		pcmd->out_port=canalid.wPORT; 
	} 
	void DeleteFileInfo(POBJECTINFO pfile) 
	{ 
		if(pfile) 
		{ 
			if(pfile->pLastCmd) 
			{ 
				delete pfile->pLastCmd; 
			} 
			delete pfile; 
		} 
	} 
	void InitializeFileInfo(POBJECTINFO pfile, 
							UNI_DWORD dwFileID, 
							UNI_DWORD dwFileSize, 
							E_FILE_ACT eAct, 
							char *sendName, 
							char *fileName, 
							HCANAL hcanal) 
	{ 
		memset(pfile,0,sizeof(OBJECTINFO)); 
		pfile->BaseInfo.dwFileID=dwFileID; 
		pfile->eAct=eAct; 
		pfile->BaseInfo.dwFileSize=dwFileSize; 
		strncpy(pfile->BaseInfo.sendName,sendName,sizeof(pfile->BaseInfo.sendName)); 
		strncpy(pfile->BaseInfo.fileName,fileName,sizeof(pfile->BaseInfo.fileName)); 
		pfile->hfrom=hcanal; 
		pfile->hsvr=hcanal; 
		pfile->dwTaskMaxPackSize=MAX_PACK_SIZE; 
	} 
 
//	UNI_BOOL GetCanalIdFromSvr(HCANAL hsvr,H_CANAL_ID &canalId,UNI_DWORD dwTimeOutMs); 
public: 
 
	static CZsP2pBlock* _Open(ZsP2pEventHandle  *pEvent,char *username,UNI_WORD dwLocalPort,UNI_DWORD dwLocalIp=INADDR_ANY); 
	void Close(); 
	void UserCancelSend(UNI_DWORD dwFileID,char *toWho,UNI_BOOL bKernel=UNI_FALSE); 
	UNI_BOOL UserStartRecv(UNI_DWORD dwFileID,char *fromWho,char *fileName,char *pathName,UNI_DWORD dwStartOffset); 
	void UserCancelRecv(UNI_DWORD dwFileID,char *fromWho,UNI_BOOL bKernel=UNI_FALSE); 
 
	UNI_BOOL EnableRecvFrom(UNI_DWORD dwSvrIp,UNI_WORD dwSvrPort); 
	UNI_BOOL CreateSendCanal(UNI_DWORD dwFileID,char *fileName,UNI_DWORD dwFileSize,char *toWho,char *pathName,UNI_DWORD dwIp,UNI_WORD port); 
	void DestorySendCanal(UNI_DWORD dwFileID,char *toWho); 
	UNI_BOOL UserStartSend(UNI_DWORD dwFileID,char *toWho); 
protected: 
 
	UNI_DWORD GetTransCount(); 
	UNI_BOOL Open(ZsP2pEventHandle *pEvent,char *username,UNI_WORD dwLocalPort,UNI_DWORD dwLocalIp=INADDR_ANY);	 
 
	CZsP2pBlock(); 
	virtual ~CZsP2pBlock(); 
 
 
	 
	void Run(HCurrentThread ¤tThread); 
	void OnSvrFileWait(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void OnSvrFileNo(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void OnSvrFileReq(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void OnSvrFileAck(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void SendOnFileSuccess(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void SendOnFileNext(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void SendOnFileCancel(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void SendOnReadyTest(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom); 
	UNI_BOOL RecvOnAckTimeOut(OBJECTINFO * pfile); 
	UNI_BOOL SendOnAckTimeOut(OBJECTINFO *pfile); 
	void RecvOnFileSuccessAck(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void RecvOnFileSendCancel(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void RecvOnFileEnd(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void RecvOnFileData(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom); 
	void RecvOnReadyOk(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom); 
	void ALLOnSvrAckHere(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom); 
	friend class X_Canals;  
	friend class X_SendTimeOut; 
	friend class X_RecvTimeOut; 
	friend class UDPtaskList; 
	friend class X_Cancel; 
	friend class X_Delete; 
}; 
 
#endif // !defined(AFX_HP2PBLOCK_H__B3D1AFBD_2E56_409E_AB2B_50952DC3FF02__INCLUDED_)