www.pudn.com > UDP文件传输.rar > ZsP2pBlock.cpp


// HP2PBlock.cpp: implementation of the HP2PBlock class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "ZsP2PBlock.h" 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
CZsP2pBlock::CZsP2pBlock() 
{ 
	this->m_pEvent =UNI_NULL; 
	this->m_UDPCanal.pP2p=this; 
	this->m_recvTimeOut.m_pThis=this; 
	this->m_sendTimeOut.m_pThis=this; 
	this->m_Cancel.m_pThis=this; 
	m_Delete.m_pThis=this; 
	this->m_MyName[0]=0; 
//	m_ThreadDeleteMe=false; 
	strncpy(this->m_MyPassWord,"******",sizeof(this->m_MyPassWord)); 
} 
 
CZsP2pBlock::~CZsP2pBlock() 
{ 
 
} 
void CZsP2pBlock::RecvOnReadyOk(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	UDPFILE_CMD *cmd; 
	OBJECTINFO *pOld; 
	printf("RecvOnReadyOk  \n"); 
	if(cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
		if((pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))!=UNI_NULL) 
		{ 
			if(cmd=pOld->pLastCmd) 
			{ 
				if(cmd->head.cmd==UDP_READY_TEST) 
				{ 
					pOld->dwStreamPackCount=0; 
					pOld->dwTimeOutCount=0; 
					if(m_pEvent->UI_OnFileReq(&pOld->BaseInfo,pOld->dwFileOffset,pOld->BaseInfo.pExtra)) 
					{ 
						//现在就开始 
						pOld->eAct=FILE_ACT_ACCEPT; 
						this->InitializeCmd(&cmd->head,pOld->BaseInfo.dwFileID, 
							pOld->BaseInfo.dwFileSize, 
							pOld->dwFileOffset, 
							pcmd->head.user_name, 
							UDP_FILE_NEXT,pOld->myCanalId); 
						 
 
						cmd->head.other_info=pOld->dwTaskMaxPackSize; 
						this->m_UDPCanal.Send(pOld->hfrom,cmd,sizeof(cmd->head)+cmd->head.other_len +cmd->head.user_data_len); 
						pOld->dwTickCount=UNI_GetTickCount(); 
					} 
					else 
					{//以后开始 
						delete pOld->pLastCmd; 
						pOld->pLastCmd=UNI_NULL; 
					} 
					 
				} 
			} 
			if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE) 
			{ 
				//出错 
				this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
				this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
 
				DeleteFileInfo(pOld); 
			} 
		} 
	} 
 
} 
void CZsP2pBlock::RecvOnFileData(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	UDPFILE_CMD *cmd; 
	OBJECTINFO *pOld; 
	 
	if(pcmd->head.user_data_len !=0 && 
			cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
		if((pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))!=UNI_NULL 
				&& pOld->BaseInfo.dwFileSize ==pcmd->head.stream_size ) 
		{ 
			if(cmd=pOld->pLastCmd) 
			{ 
				if(pOld->eAct==FILE_ACT_ACCEPT) 
				{ 
					pOld->dwStreamPackCount++; 
					 
					if(cmd->head.cmd==UDP_FILE_NEXT) 
					{ 
						pOld->dwTimeOutCount=0; 
						cmd->head.trans_id=pcmd->head.trans_id; 
						cmd->head.stream_size  =pcmd->head.stream_size ; 
						cmd->head.cmd =UDP_FILE_NEXT; 
						if(pOld->dwFileOffset ==pcmd->head.pack_id )//正是想要的数据 
						{ 
							pOld->dwFileOffset+=pcmd->head.user_data_len; 
							cmd->head.pack_id  =pOld->dwFileOffset; 
							 
							//通知上层,以便界面有所表示和保存数据! 
							this->m_pEvent->UI_OnSaveData(&pOld->BaseInfo, 
								pcmd->head.pack_id , 
								pcmd->head.user_data_len, 
								((char *)pcmd)+pcmd->head.other_len+sizeof(pcmd->head)); 
								 
								 
						} 
						cmd->head.other_info=pOld->dwTaskMaxPackSize; 
					} 
				} 
				else 
				{ 
					cmd->head.cmd=UDP_FILE_RECV_CANCEL; 
				} 
				this->m_UDPCanal.Send(pOld->hfrom,cmd,sizeof(cmd->head)+cmd->head.other_len +cmd->head.user_data_len); 
				pOld->dwTickCount=UNI_GetTickCount(); 
			} 
			if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE) 
			{ 
				//出错 
				this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
				this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
 
				DeleteFileInfo(pOld); 
			} 
		} 
	} 
} 
 
void CZsP2pBlock::RecvOnFileEnd(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	UDPFILE_CMD* cmd; 
	OBJECTINFO *pOld; 
	 
	if(	cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
		if((pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name))!=UNI_NULL 
				&& pOld->BaseInfo.dwFileSize ==pcmd->head.stream_size ) 
		{ 
			if(cmd=pOld->pLastCmd) 
			if(pOld->eAct==FILE_ACT_ACCEPT) 
			{ 
				if(cmd->head.cmd==UDP_FILE_NEXT) 
				{ 
					pOld->dwStreamPackCount++; 
					pOld->dwTimeOutCount=0; 
					cmd->head.trans_id=pcmd->head.trans_id; 
					cmd->head.stream_size  =pcmd->head.stream_size ; 
					cmd->head.cmd =UDP_FILE_NEXT; 
					if(pOld->dwFileOffset ==pcmd->head.pack_id )//正是想要的数据 
					{ 
						if(pOld->dwFileOffset+pcmd->head.user_data_len==pOld->BaseInfo.dwFileSize) 
						{ 
							//文件完整则成功,否则要想要的哪块 
							cmd->head.cmd =UDP_FILE_SUCCESS; 
							pOld->dwFileOffset+=pcmd->head.user_data_len; 
							 
							//通知上层,以便界面有所表示和保存数据! 
							this->m_pEvent->UI_OnSaveData(&pOld->BaseInfo, 
								pcmd->head.pack_id , 
								pcmd->head.user_data_len, 
								((char *)pcmd)+pcmd->head.other_len+sizeof(pcmd->head)); 
							pOld->bResult=UNI_TRUE;//传输已成功 
							this->m_pEvent->UI_OnRecvOver(&pOld->BaseInfo); 
						} 
						cmd->head.pack_id  =pOld->dwFileOffset; 
					} 
					cmd->head.other_info=pOld->dwTaskMaxPackSize; 
 
				} 
			} 
			else 
			{ 
				cmd->head.cmd=UDP_FILE_RECV_CANCEL; 
			} 
			this->m_UDPCanal.Send(pOld->hfrom,cmd,sizeof(cmd->head)+cmd->head.other_len +cmd->head.user_data_len); 
			pOld->dwTickCount=UNI_GetTickCount(); 
 
		 
 
			if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE) 
			{ 
				//出错 
				this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
				this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
				DeleteFileInfo(pOld); 
			} 
		} 
	} 
} 
 
void CZsP2pBlock::RecvOnFileSendCancel(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	/* 
	收到这条响应,下一步要发送UDP_FILE_SUCCESS命令以先知对方结束这次传输. 
	对方应以UDP_FILE_SUCCESS_ACK做为响应. 
	但在收到对方的UDP_FILE_SUCCESS_ACK前,本次传输已被成功的取消了. 
	如果收不到UDP_FILE_SUCCESS_ACK也认为是成功了! 
	*/ 
	UDPFILE_CMD *cmd; 
	OBJECTINFO *pOld; 
	 
	if(cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
		if(pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name)) 
		{ 
			pOld->bResult=UNI_FALSE; 
		//	pOld->dwRecvPackCount++; 
			if(pOld->eAct !=FILE_ACT_REFUSE) 
			{ 
				//如果用户还未开始下载,要通知上层发送方已取消! 
				this->m_pEvent->UI_OnCancelBySend(&pOld->BaseInfo); 
				pOld->eAct =FILE_ACT_REFUSE; 
			} 
			if(pOld->pLastCmd==UNI_NULL) 
			{ 
				if(cmd=pOld->pLastCmd=new UDPFILE_CMD) 
				{ 
					this->InitializeCmd(&cmd->head, 
						pOld->BaseInfo.dwFileID, 
						pOld->BaseInfo.dwFileSize, 
						pOld->dwFileOffset, 
						pcmd->head.user_name, 
						UDP_FILE_SUCCESS,pOld->myCanalId); 
				} 
			} 
			if(cmd=pOld->pLastCmd) 
			{ 
				cmd->head.cmd=UDP_FILE_SUCCESS; 
				this->m_UDPCanal.Send(pOld->hfrom,cmd,sizeof(cmd->head)+cmd->head.other_len +cmd->head.user_data_len); 
				pOld->dwTickCount=UNI_GetTickCount(); 
			} 
			if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE) 
			{ 
				//出错 
				this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
				this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
				DeleteFileInfo(pOld); 
			} 
		}		 
	} 
} 
 
void CZsP2pBlock::RecvOnFileSuccessAck(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	UDPFILE_CMD *cmd; 
	OBJECTINFO *pOld; 
	 
	if(	cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
		 
			if(pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name)) 
			{ 
				cmd=pOld->pLastCmd; 
				if(cmd!=NULL && cmd->head.cmd==UDP_FILE_SUCCESS) 
				{ 
					delete cmd; 
					pOld->pLastCmd=UNI_NULL; 
 
					if(pOld->hfrom) 
						this->m_UDPCanal.CloseCanal(pOld->hfrom);//关闭通道	 
					this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
					DeleteFileInfo(pOld); 
				} 
				else if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE) 
				{ 
					//出错 
					this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
					this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
					DeleteFileInfo(pOld); 
				} 
				 
			} 
	} 
} 
void CZsP2pBlock::SendOnReadyTest(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	UDPFILE_CMD *cmd; 
	OBJECTINFO *pOld; 
#ifdef _DEBUG 
	printf("recv UDP_READY_TEST trans_id=%d,user_name=%s!\r\n",pcmd->head.trans_id,pcmd->head.user_name); 
#endif 
	if(cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
		 
			if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name)) 
			{ 
				if(cmd=(UDPFILE_CMD *)new UDPFILE_CMD) 
				{ 
					this->InitializeCmd(&cmd->head,pOld->BaseInfo.dwFileID,pOld->BaseInfo.dwFileSize, 
						pcmd->head.pack_id, 
						pOld->BaseInfo.sendName,UDP_READY_OK,pOld->myCanalId); 
					cmd->head.pack_id  =pcmd->head.pack_id ; 
					this->m_UDPCanal.Send(pOld->hfrom,cmd,cmd->head.user_data_len +cmd->head.other_len+sizeof(cmd->head)); 
					delete cmd; 
				} 
				if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE) 
				{ 
					//出错 
					this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
					this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
					DeleteFileInfo(pOld); 
				}	 
			} 
	} 
 
} 
 
void CZsP2pBlock::ALLOnSvrAckHere(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	OBJECTINFO *pOld; 
	if(cmdSize>=sizeof(pcmd->head)) 
	{ 
 
		if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.append_str)) 
		{ 
			if(pOld->pLastCmd) 
			{ 
				if(pOld->pLastCmd->head.cmd==UDP_CLIENT_HERE) 
				{ 
					if(pOld->hsvr==hfrom && pOld->hfrom==hfrom) 
					{ 
						pOld->myCanalId.dwIP=pcmd->head.out_ip; 
						pOld->myCanalId.wPORT=pcmd->head.out_port; 
					} 
					delete pOld->pLastCmd; 
					pOld->pLastCmd=UNI_NULL; 
				} 
			} 
			 
			if(this->m_SendFiles.AddTail(pOld)) 
				return ; 
			this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
			this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
			this->DeleteFileInfo(pOld); 
		} 
	} 
} 
 
void CZsP2pBlock::SendOnFileCancel(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	UDPFILE_CMD *cmd; 
	OBJECTINFO *pOld; 
	if(	cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
		 
			if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name)) 
			{ 
				pOld->bResult =UNI_FALSE;//传输被接收方中断 
				 
 
				if(cmd=(UDPFILE_CMD *)new UDPFILE_CMD) 
				{ 
					this->InitializeCmd(&cmd->head, 
						pOld->BaseInfo.dwFileID, 
						pOld->BaseInfo.dwFileSize, 
						pcmd->head.pack_id, 
						pOld->BaseInfo.sendName,UDP_FILE_SUCCESS_ACK,pOld->myCanalId); 
					 
					this->m_UDPCanal.Send(pOld->hfrom,cmd,cmd->head.user_data_len +sizeof(cmd->head)+cmd->head.other_len); 
					delete cmd; 
				} 
				if(pOld->eAct!=FILE_ACT_REFUSE) 
				{ 
					//如果是服务端已取消,就不再通知上层! 
					this->m_pEvent->UI_OnCancelByRecv(&pOld->BaseInfo); 
				} 
				if(pOld->hfrom) 
					this->m_UDPCanal.CloseCanal(pOld->hfrom); 
				this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
				DeleteFileInfo(pOld); 
			} 
	} 
} 
 
void CZsP2pBlock::SendOnFileNext(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	UDPFILE_CMD *cmd; 
	OBJECTINFO *pOld; 
	UNI_DWORD dwMaxPackSize; 
	int len=0; 
 
	if(	cmdSize >= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
			if(pcmd->head.other_info>MAX_PACK_SIZE)pcmd->head.other_info=MAX_PACK_SIZE; 
			if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name)) 
			{ 
			//	if(pOld->eAct!=FILE_ACT_REFUSE) 
				{ 
					dwMaxPackSize=pcmd->head.other_info<1024?1024:pcmd->head.other_info; 
					if(cmd=(UDPFILE_CMD *)new char[dwMaxPackSize]) 
					{ 
						this->InitializeCmd(&cmd->head, 
							pOld->BaseInfo.dwFileID, 
							pOld->BaseInfo.dwFileSize, 
							pcmd->head.pack_id, 
							pOld->BaseInfo.sendName, 
							UDP_FILE_SEND_CANCEL,pOld->myCanalId);	 
 
						if(pOld->eAct!=FILE_ACT_REFUSE) 
						{ 
							//调用上层读文件数据 
							cmd->head.user_data_len=(UNI_DWORD)(len=this->m_pEvent->UI_OnReadData(&pOld->BaseInfo, 
								pcmd->head.pack_id, 
								dwMaxPackSize-sizeof(cmd->head), 
								&cmd->fileName)); 
							if(len<0) 
							{ 
								//读文件错误 
	#ifdef _DEBUG 
								printf("read file error!\r\n"); 
	#endif 
							} 
							else 
							{ 
								pOld->dwFileOffset=pcmd->head.pack_id +len; 
								if(cmd->head.user_data_len==dwMaxPackSize-sizeof(cmd->head)) 
								{ 
									cmd->head.cmd =UDP_FILE_DATA; 
								} 
								else if(cmd->head.user_data_len>=0) 
								{ 
									cmd->head.cmd =UDP_FILE_END; 
								}	 
								cmd->head.pack_id =pcmd->head.pack_id ; 
							} 
						} 
						this->m_UDPCanal.Send(pOld->hfrom,cmd,cmd->head.user_data_len + 
							sizeof(cmd->head)+ 
							cmd->head.other_len); 
						delete cmd; 
#ifdef _DEBUG 
						printf("ACK FILE_NEXT send date to(%s,%d)!\r\n",HSocket::getipstr(m_UDPCanal.GetCanalAddr(pOld->hfrom)->dwIP),m_UDPCanal.GetCanalAddr(pOld->hfrom)->wPORT); 
#endif 
					}//new cmd 
				}//if(pOld->eAct!=FILE_ACT_REFUSE) 
 
				if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE) 
				{ 
						//出错 
					this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
					this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
					DeleteFileInfo(pOld); 
				}	 
			}	 
	} 
} 
 
void CZsP2pBlock::SendOnFileSuccess(PUDPFILE_CMD pcmd, UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	OBJECTINFO *pOld; 
	if(cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
		 
			if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name)) 
			{ 
				pOld->bResult =pOld->dwFileOffset ==pOld->BaseInfo.dwFileSize ?UNI_TRUE:UNI_FALSE; 
				if(pOld->eAct!=FILE_ACT_REFUSE) 
				{ 
					//如果已取消,就不再通知上层! 
					this->m_pEvent->UI_OnSendOver(&pOld->BaseInfo); 
				} 
				this->InitializeCmd(&pcmd->head, 
					pOld->BaseInfo.dwFileID, 
					pOld->BaseInfo.dwFileSize, 
					pcmd->head.pack_id, 
					pOld->BaseInfo.sendName,UDP_FILE_SUCCESS_ACK,pOld->myCanalId); 
				this->m_UDPCanal.Send(pOld->hfrom,pcmd,pcmd->head.user_data_len +sizeof(pcmd->head)); 
				/////////////////////////////////////////////////////////////////////// 
				if(pOld->hfrom) 
					this->m_UDPCanal.CloseCanal(pOld->hfrom); 
 
				this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
				DeleteFileInfo(pOld); 
			} 
				 
	} 
} 
void CZsP2pBlock::OnSvrFileReq(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfromSvr) 
{ 
	/* 
	当服务通知有文件来到时,接收方只能回答知道了! 
	然后客户要做的是建立与发送者的通道和文件信息,并通知上层! 
	*/ 
	OBJECTINFO *pOld; 
	HCANAL hfrom; 
	H_INET_ADDR *paddr; 
	if(	(pcmd->head.other_len >1 ) &&  
			(cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) && 
			pcmd->fileName[pcmd->head.other_len-1]==0 && 
			pcmd->head.user_data_len>=6) 
	{ 
		if(pOld=this->m_recvFiles.FindFile(pcmd->head.trans_id,pcmd->head.user_name)) 
		{ 
			if(this->m_recvFiles.AddTail(pOld)) 
				return; 
			this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
			this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
			delete pOld; 
			return; 
		} 
		if(hfrom=this->m_UDPCanal.CreateCanal(pcmd->head.out_ip,pcmd->head.out_port)) 
		{ 
			paddr=this->m_UDPCanal.GetCanalAddr(hfrom); 
			paddr->dwIP=pcmd->head.use_ip; 
			paddr->wPORT=pcmd->head.use_port; 
			if(pOld= new OBJECTINFO) 
			{ 
				this->InitializeFileInfo(pOld,pcmd->head.trans_id,pcmd->head.stream_size,FILE_ACT_WAIT,pcmd->head.user_name,pcmd->fileName,hfrom); 
				pOld->hsvr=hfromSvr; 
				//获取网络ID 
				pOld->myCanalId.dwIP=*((UNI_DWORD *)&pcmd->fileName[pcmd->head.other_len]); 
				pOld->myCanalId.wPORT=*((UNI_WORD *)&pcmd->fileName[pcmd->head.other_len+sizeof(UNI_DWORD)]); 
				pcmd->head.use_ip=this->m_MyIp; 
				pcmd->head.use_port=this->m_MyPort; 
				 
				pcmd->head.cmd=UDP_CLIENT_ACK;// 
				pcmd->head.use_ip=this->m_MyIp; 
				pcmd->head.use_port=this->m_MyPort; 
				strncpy(pcmd->head.append_str,pcmd->head.user_name,sizeof(pcmd->head.append_str)); 
				strncpy(pcmd->head.user_name,this->m_MyName,sizeof(pcmd->head.user_name)); 
				pcmd->head.other_len=0; 
				pcmd->head.user_data_len=0; 
				this->m_UDPCanal.Send(pOld->hsvr,pcmd,sizeof(pcmd->head));//回答服务器知道了! 
				if(pOld->pLastCmd=new UDPFILE_CMD) 
				{ 
					this->InitializeCmd(&pOld->pLastCmd->head, 
						pOld->BaseInfo.dwFileID, 
						pOld->BaseInfo.dwFileSize, 
						pOld->dwFileOffset, 
						pOld->BaseInfo.sendName, 
						UDP_READY_TEST,pOld->myCanalId); 
					pOld->pLastCmd->head.other_info=1024; 
					this->m_UDPCanal.Send(hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head)+pOld->pLastCmd->head.other_len); 
	#ifdef _DEBUG 
					printf("\r\n\r\n\r\nsend UDP_READY_TEST=%d to %s\r\n",pOld->pLastCmd->head.cmd,pOld->BaseInfo.sendName); 
	#endif  
					pOld->dwTickCount=UNI_GetTickCount(); 
					if(this->m_recvFiles.AddTail(pOld)) 
						return ; 
					delete pOld->pLastCmd; 
				} 
				delete pOld; 
			} 
			this->m_UDPCanal.CloseCanal(hfrom); 
		} 
	} 
 
} 
void CZsP2pBlock::OnSvrFileNo(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfromSvr) 
{ 
	/* 
	服务代替接收方取消或拒绝一个文件的传输, 
	所以在发送文件列表中找! 
	*/ 
	OBJECTINFO *pOld; 
	HCANAL hfrom; 
	if(	cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
			if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.append_str)) 
			{ 
				if(pOld->eAct==FILE_ACT_WAIT) 
				{ 
					hfrom=pOld->hfrom; 
					//通知上层已被取消,唯一原因是找不到接收方! 
					m_pEvent->UI_OnFileRefuse(&pOld->BaseInfo); 
					 
					/////////////////删除通道与文件信息 
					if(pOld->hfrom) 
						this->m_UDPCanal.CloseCanal(pOld->hfrom); 
 
					this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
					DeleteFileInfo(pOld); 
					 
				} 
				else 
				{ 
					if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE) 
					{ 
						this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
						this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
						DeleteFileInfo(pOld); 
					} 
				} 
			} 
	} 
} 
//UDP_SVR_FILE_WAIT 
void CZsP2pBlock::OnSvrFileWait(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	/* 
	发送方处理此命令,且不必回答,仅是过一段时间再次以UDP_CLIENT_FILE_REQ询问服务器 
	*/ 
	OBJECTINFO *pOld; 
	if(cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len) 
	{ 
			if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.append_str)) 
			{ 
				if(pOld->eAct==FILE_ACT_WAIT)//&& pOld->pLastCmd!=UNI_NULL) 
				{ 
					//说明正在等待服务器的应答! 
					pOld->dwTimeOutCount=0; 
					if(pOld->pLastCmd) 
					{ 
						pOld->pLastCmd->head.other_info=pcmd->head.other_info; 
					} 
				} 
				if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE) 
				{ 
					//出错 
					this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
					this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
					DeleteFileInfo(pOld); 
				} 
			} 
	} 
} 
//UDP_SVR_FILE_ACK 
void CZsP2pBlock::OnSvrFileAck(PUDPFILE_CMD pcmd,UNI_DWORD cmdSize,HCANAL hfrom) 
{ 
	/* 
	服务器给出接收方的IP和通道号(不是端口号),此命令由文件发送方处理! 
	pcmd->head.usePort是通道号而不是端口号 
	*/ 
	OBJECTINFO *pOld; 
	HCANAL hcanl; 
	H_INET_ADDR *paddr; 
	if(	cmdSize>= pcmd->head.other_len+sizeof(pcmd->head)+pcmd->head.user_data_len && pcmd->head.user_data_len>=6) 
	{ 
			if(pOld=this->m_SendFiles.FindFile(pcmd->head.trans_id,pcmd->head.append_str)) 
			{ 
				if(pOld->eAct==FILE_ACT_WAIT) 
				{ 
					pOld->eAct=FILE_ACT_ACCEPT; 
					//说明正在等待服务器的应答! 
					memcpy(&pOld->myCanalId,&pcmd->fileName[pcmd->head.other_len],sizeof(pOld->myCanalId)); 
					if(hcanl=this->m_UDPCanal.CreateCanal(pcmd->head.out_ip,pcmd->head.out_port/*通道号*/)) 
					{ 
						paddr=this->m_UDPCanal.GetCanalAddr(hcanl); 
						paddr->dwIP=pcmd->head.out_ip; 
						paddr->wPORT=pcmd->head.use_port; 
						pOld->hfrom=hcanl; 
						if(pOld->pLastCmd!=UNI_NULL)//此处不应为空,因为它正等服务的UDP_SVR_FILE_ACK响应! 
						{ 
						//	this->InitializeCmd(&pOld->pLastCmd->head ,pOld->BaseInfo.dwFileID,pOld->BaseInfo.dwFileSize,0,pOld->BaseInfo.sendName,UDP_CLIENT_HERE,pOld->myCanalId); 
						//	this->m_UDPCanal.Send(pOld->hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head)); 
							delete pOld->pLastCmd; 
							pOld->pLastCmd=UNI_NULL; 
						} 
						ContinueConnect(hcanl,pOld->myCanalId); 
					} 
				} 
				if(this->m_SendFiles.AddTail(pOld)==UNI_FALSE) 
				{ 
					//出错 
					this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
					this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
					DeleteFileInfo(pOld); 
				} 
			} 
	} 
} 
UNI_BOOL CZsP2pBlock::UserStartRecv(UNI_DWORD dwFileID,char *fromWho,char *fileName,char *pathName,UNI_DWORD dwStartOffset) 
{ 
	OBJECTINFO *pOld; 
	if(pOld=this->m_recvFiles.FindFile(dwFileID,fromWho)) 
	{ 
		this->m_pEvent->UI_Initialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra,pathName); 
		pOld->dwFileOffset=dwStartOffset; 
		pOld->eAct=FILE_ACT_ACCEPT; 
		if(pOld->pLastCmd=new UDPFILE_CMD) 
		{ 
			this->InitializeCmd(&pOld->pLastCmd->head, 
				dwFileID,pOld->BaseInfo.dwFileSize, 
				pOld->dwFileOffset, 
				fromWho, 
				UDP_FILE_NEXT,pOld->myCanalId); 
			this->m_UDPCanal.Send(pOld->hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head)); 
			pOld->dwTickCount=UNI_GetTickCount(); 
			if(this->m_recvFiles.AddTail(pOld)==UNI_TRUE) 
				return UNI_TRUE; 
			this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
			DeleteFileInfo(pOld);	 
		} 
	} 
#ifdef _DEBUG 
	char TempBuf[512]; 
	sprintf(TempBuf,"start recv failed id=%d  fromWho=%s\n",dwFileID,fromWho); 
	P2P_WriteLog("c:\\p2plog.txt",TempBuf); 
#endif 
 
	return UNI_FALSE; 
} 
void CZsP2pBlock::UserCancelRecv(UNI_DWORD dwFileID,char *fromWho,UNI_BOOL bKernel) 
{ 
	/* 
	向发送方发UDP_FILE_RECV_CANCEL命令! 
	等其响应UDP_FILE_SUCCESS_ACK时清内存 
	*/ 
#ifdef _DEBUG 
	char TempBuf[512]; 
	sprintf(TempBuf,"id=%d  fromWho=%s\n",dwFileID,fromWho); 
	P2P_WriteLog("c:\\p2plog.txt",TempBuf); 
#endif 
	OBJECTINFO *pOld; 
	if(pOld=this->m_recvFiles.FindFile(dwFileID,fromWho)) 
	{ 
		if(pOld->eAct!=FILE_ACT_REFUSE) 
		{ 
			pOld->eAct=FILE_ACT_REFUSE; 
			if(pOld->hfrom)//hfrom是在响应服务器的REQ时建立的 
			{ 
				if(pOld->pLastCmd==UNI_NULL) 
						pOld->pLastCmd=new UDPFILE_CMD; 
				if(pOld->pLastCmd) 
				{ 
					this->InitializeCmd(&pOld->pLastCmd->head, 
						pOld->BaseInfo.dwFileID, 
						pOld->BaseInfo.dwFileSize, 
						pOld->dwFileOffset, 
						pOld->BaseInfo.sendName,UDP_FILE_RECV_CANCEL,pOld->myCanalId); 
					this->m_UDPCanal.Send(pOld->hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head)); 
					pOld->dwTickCount=UNI_GetTickCount(); 
				} 
			} 
		} 
		if(this->m_recvFiles.AddTail(pOld)==UNI_FALSE) 
		{ 
			//出错 
			this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
			this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
			DeleteFileInfo(pOld); 
		} 
	} 
	else if(bKernel==UNI_FALSE) 
	{ 
		if(pOld=new OBJECTINFO) 
		{ 
			InitializeFileInfo(pOld,dwFileID,0,FILE_ACT_REFUSE,fromWho,"",UNI_NULL); 
			if(m_CancelFiles.AddTail(pOld)==UNI_FALSE) 
			{ 
				delete pOld; 
			} 
		} 
	} 
} 
void CZsP2pBlock::UserCancelSend(UNI_DWORD dwFileID,char *toWho,UNI_BOOL bKernel) 
{ 
	/* 
	向对方发送UDP_FILE_SEND_CANCEL命令,直到等到UDP_FILE_SUCCESS后 
	返回UDP_FILE_SUCCESS_ACK才能真正释放内存 
	*/ 
 
	UDPFILE_CMD *pcmd; 
	OBJECTINFO *pOld; 
	if(pOld=this->m_SendFiles.FindFile(dwFileID,toWho)) 
	{ 
		if(pOld->eAct==FILE_ACT_ACCEPT) 
		{ 
			pOld->eAct=FILE_ACT_REFUSE; 
			if(pcmd=new UDPFILE_CMD) 
			{ 
				this->InitializeCmd(&pcmd->head, 
					pOld->BaseInfo.dwFileID, 
					pOld->BaseInfo.dwFileSize, 
					pOld->dwFileOffset, 
					pOld->BaseInfo.sendName,UDP_FILE_SEND_CANCEL,pOld->myCanalId); 
				this->m_UDPCanal.Send(pOld->hfrom,pcmd,sizeof(pcmd->head)); 
				pOld->dwTickCount=UNI_GetTickCount(); 
			} 
			if(pOld->pLastCmd) 
				delete pOld->pLastCmd; 
			pOld->pLastCmd=pcmd; 
			if(this->m_SendFiles.AddTail(pOld)==UNI_TRUE) 
				return; 
		} 
		//应通知上层因出错无法断续,但没有 
		this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
		this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
		DeleteFileInfo(pOld); 
	} 
	else if(bKernel==UNI_FALSE) 
	{ 
		if(pOld=new OBJECTINFO) 
		{ 
			InitializeFileInfo(pOld,dwFileID,1,FILE_ACT_REFUSE,toWho,"",UNI_NULL); 
			if(m_CancelFiles.AddTail(pOld)==UNI_FALSE) 
			{ 
				delete pOld; 
			} 
		} 
	} 
 
} 
 
UNI_BOOL CZsP2pBlock::SendOnAckTimeOut(OBJECTINFO *pfile) 
{ 
	PUDPFILE_CMD pcmd; 
	HCANAL hTo; 
	if(pfile!=UNI_NULL && 
		(pcmd=pfile->pLastCmd)!=UNI_NULL &&  
		(hTo=pfile->hfrom)!=UNI_NULL) 
	{ 
		/* 
		SEND方对服务器有超时,对取消也有超时!对接收方没有超时! 
		对于超时未得到响应的命令一般都要重发! 
		重发超过三次认为任务失败,除通知上层外还要删除文件信息,关闭通道 
		*/ 
		pfile->dwTimeOutCount++; 
		if(pfile->dwTimeOutCount>3) 
		{ 
			// 
			if(pcmd->head.cmd==UDP_CLIENT_FILE_REQ||UDP_FILE_SEND_CANCEL==pcmd->head.cmd) 
			{ 
				//如果用户正在等数据则通知上层失败!其它均是正常结束 
				this->m_pEvent->UI_OnSendTimeOut(&pfile->BaseInfo); 
			} 
			this->m_UDPCanal.CloseCanal(pfile->hfrom); 
			this->m_pEvent->UI_UnInitialize(&pfile->BaseInfo,pfile->BaseInfo.pExtra); 
			delete pfile; 
			return UNI_TRUE;//返回TRUE将被删除 
		} 
		else 
		{ 
#ifdef _DEBUG 
			printf("\t\t timeout resend cmd:%d (UDP_CLIENT_FILE_REQ=%d)\r\n",pcmd->head.cmd,UDP_CLIENT_FILE_REQ); 
#endif 
			this->m_UDPCanal.Send(pfile->hfrom,pcmd,sizeof(pcmd->head)+pcmd->head.user_data_len+pcmd->head.other_len); 
			pfile->dwTickCount =UNI_GetTickCount(); 
 
		} 
	} 
	return UNI_FALSE; 
} 
 
UNI_BOOL CZsP2pBlock::RecvOnAckTimeOut(OBJECTINFO *pfile) 
{ 
	PUDPFILE_CMD pcmd; 
	HCANAL hTo; 
	H_INET_ADDR *paddr1,*paddr2; 
	UNI_DWORD i; 
	static UNI_DWORD packsizes[10]={1024*10,1024*5,1024*2,1024,1024,1024,1024,1024,1024,1024}; 
	if(pfile!=UNI_NULL && 
		(pcmd=pfile->pLastCmd)!=UNI_NULL &&  
		(hTo=pfile->hfrom)!=UNI_NULL) 
	{ 
		/* 
		对于超时未得到响应的命令一般都要重发! 
		*/ 
		pfile->dwTimeOutCount++; 
 
		paddr1=this->m_UDPCanal.GetCanalAddr(pfile->hfrom); 
		paddr2=this->m_UDPCanal.GetCanalAddr(pfile->hsvr); 
		if((UDP_FILE_RECV_CANCEL==pcmd->head.cmd ||	this->m_bRuning==UNI_FALSE || (paddr1->dwIP ==paddr2->dwIP && paddr1->wPORT==paddr2->wPORT)) && 
				(pfile->dwTimeOutCount>5 )) 
		{ 
 
			if(pcmd->head.cmd==UDP_FILE_NEXT) 
			{ 
				//如果用户正在等数据则能知上层失败!其它均是正常结束 
				this->m_pEvent->UI_OnRecvTimeOut(&pfile->BaseInfo); 
			} 
			this->m_UDPCanal.CloseCanal(pfile->hfrom); 
			this->m_pEvent->UI_UnInitialize(&pfile->BaseInfo,pfile->BaseInfo.pExtra); 
			DeleteFileInfo(pfile); 
			return UNI_TRUE; 
		} 
		else if(pfile->pLastCmd->head.cmd==UDP_READY_TEST)//	pfile->dwRecvPackCount==0) 
		{ 
			if(pfile->dwTimeOutCount>3)//3次外发从未收到过对方的响应 
			{ 
				paddr1->dwIP=paddr2->dwIP; 
				paddr1->wPORT=paddr2->wPORT; 
				pfile->dwTimeOutCount=0; 
				pfile->dwTaskMaxPackSize=1024; 
			} 
		} 
		if(pfile->pLastCmd->head.cmd==UDP_FILE_NEXT) 
		{ 
			i=pfile->dwTimeOutCount>sizeof(packsizes)/sizeof(packsizes[0]) ? sizeof(packsizes)/sizeof(packsizes[0])-1 : pfile->dwTimeOutCount-1; 
			if(pfile->dwTaskMaxPackSize>packsizes[i]) 
				pfile->dwTaskMaxPackSize=packsizes[i]; 
			pfile->pLastCmd->head.other_info=pfile->dwTaskMaxPackSize; 
		} 
 
#ifdef _DEBUG 
	char TempBuf[512]; 
	sprintf(TempBuf,"RecvOnAckTimeOut id=%d  sendname=%s cmd=%d\n",pfile->BaseInfo.dwFileID,pfile->BaseInfo.sendName,pcmd->head.cmd); 
	P2P_WriteLog("c:\\p2plog.txt",TempBuf); 
#endif 
 
		this->m_UDPCanal.Send(pfile->hfrom,pcmd,sizeof(pcmd->head)+pcmd->head.user_data_len+pcmd->head.other_len); 
		pfile->dwTickCount =UNI_GetTickCount(); 
 
	} 
	return UNI_FALSE; 
} 
 
void CZsP2pBlock::Run(HCurrentThread ¤tThread) 
{ 
	HCANAL read; 
 
	PUDPFILE_CMD pcmd; 
	UNI_DWORD dwSize; 
	 
 
	while(this->m_bRuning==UNI_TRUE || this->GetTransCount()>0) 
	{ 
 
		if(read=this->m_UDPCanal.ReadSelect(1000,MAX_PACK_SIZE)) 
		{ 
			if((dwSize=this->m_UDPCanal.ReadRecvedData(read,(void **)&pcmd))!=0 && pcmd!=UNI_NULL) 
			{ 
					switch(pcmd->head.cmd) 
					{ 
					//接收方要处理的命令! 
					case UDP_READY_OK: 
						this->RecvOnReadyOk(pcmd,dwSize,read); 
#ifdef _DEBUG 
						printf("\t\t recved UDP_READY_OK for(ip=%s,port=%d)!\r\n",HSocket::getipstr(pcmd->head.use_ip),pcmd->head.use_port); 
#endif 
 
						break; 
					case UDP_FILE_DATA: 
						RecvOnFileData(pcmd,dwSize,read); 
						break; 
					case UDP_FILE_SEND_CANCEL: 
						RecvOnFileSendCancel(pcmd,dwSize,read); 
						break; 
					case UDP_FILE_END: 
						RecvOnFileEnd(pcmd,dwSize,read); 
						break; 
					case UDP_FILE_SUCCESS_ACK: 
						RecvOnFileSuccessAck(pcmd,dwSize,read); 
						break; 
					//发送方要处理的命令!文件传输用"拉"方式/////////// 
					case UDP_READY_TEST: 
#ifdef _DEBUG 
						printf("\t\t recved UDP_READY_TEST for(ip=%s,port=%d)!\r\n",HSocket::getipstr(pcmd->head.use_ip),pcmd->head.use_port); 
#endif 
						this->SendOnReadyTest(pcmd,dwSize,read); 
						break; 
					case UDP_FILE_NEXT: 
						SendOnFileNext(pcmd,dwSize,read); 
						break; 
					case UDP_FILE_RECV_CANCEL: 
						SendOnFileCancel(pcmd,dwSize,read);					 
						break; 
					case UDP_FILE_SUCCESS: 
						SendOnFileSuccess(pcmd,dwSize,read); 
						break; 
					case UDP_CLIENT_HERE: 
#ifdef _DEBUG 
						printf("\t\t recved UDP_CLIENT_HERE from ()!\r\n"); 
#endif 
						break; 
////////////////////////////////////////////////////////////////////////////////////////	 
					case UDP_SVR_ACK: 
						ALLOnSvrAckHere(pcmd,dwSize,read); 
						break; 
					case UDP_SVR_FILE_WAIT: 
#ifdef _DEBUG 
						printf("\t\t recved UDP_SVR_FILE_WAIT!\r\n"); 
#endif 
						this->OnSvrFileWait(pcmd,dwSize,read); 
						break; 
					case UDP_SVR_FILE_NO: 
#ifdef _DEBUG 
						printf("\t\t recved UDP_SVR_FILE_NO!\r\n"); 
#endif 
						this->OnSvrFileNo(pcmd,dwSize,read); 
						break; 
					case UDP_SVR_FILE_ACK: 
#ifdef _DEBUG 
						printf("\t\t recved UDP_SVR_FILE_ACK for(ip=%s,port=%d)!\r\n",HSocket::getipstr(pcmd->head.use_ip),pcmd->head.use_port); 
#endif 
						this->OnSvrFileAck(pcmd,dwSize,read); 
						break; 
					case UDP_SVR_FILE_REQ: 
						//服务通知有文件到来,接收方只处理这一个命令 
#ifdef _DEBUG 
						printf("\t\t recved UDP_SVR_FILE_REQ from (ip=%s,port=%d)!\r\n",HSocket::getipstr(pcmd->head.use_ip),pcmd->head.use_port); 
#endif 
						OnSvrFileReq(pcmd,dwSize,read); 
						break; 
					} 
				this->m_UDPCanal.ReleaseRecvedData((void **)&pcmd); 
			} 
		} 
		this->m_CancelFiles.EnumItem(&this->m_Cancel,(UNI_DWORD)-1); 
		dwSize=UNI_GetTickCount(); 
		this->m_recvFiles.EnumItem(&this->m_recvTimeOut,dwSize); 
		this->m_SendFiles.EnumItem(&this->m_sendTimeOut,dwSize); 
 
		 
	} 
	this->m_UDPCanal.Close(); 
	m_CancelFiles.EnumItem(&m_Delete,0); 
	this->m_recvFiles.EnumItem(&m_Delete,0); 
	this->m_SendFiles.EnumItem(&m_Delete,0); 
	delete this; 
} 
 
UNI_BOOL CZsP2pBlock::Open(ZsP2pEventHandle *pEvent,char *username,UNI_WORD dwLocalPort,UNI_DWORD dwLocalIp) 
{ 
	if(pEvent!=UNI_NULL && 
		username!=UNI_NULL && username[0]!=0 && 
		dwLocalPort!=0 && 
		UNI_TRUE==HSocket::Initialize()) 
	{ 
		if(this->m_UDPCanal.Open(dwLocalPort,dwLocalIp)) 
		{ 
			strncpy(this->m_MyName,username,sizeof(m_MyName)); 
			m_MyIp=this->m_UDPCanal.GetLocal(m_MyPort); 
			this->m_pEvent=pEvent; 
			m_bRuning=UNI_TRUE; 
			if(this->m_WorkThread.Run(this)) 
			{ 
				return UNI_TRUE; 
			} 
			m_bRuning=UNI_FALSE; 
			this->m_UDPCanal.Close(); 
		} 
		HSocket::UnInitialize(); 
	} 
	return UNI_FALSE; 
} 
UNI_BOOL CZsP2pBlock::EnableRecvFrom(UNI_DWORD dwSvrIp,UNI_WORD dwSvrPort) 
{ 
 
	HCANAL hsvr; 
	if(hsvr=this->m_UDPCanal.CreateCanal(dwSvrIp,dwSvrPort)) 
	{ 
		this->m_UDPCanal.ContinueConnect(hsvr); 
		return UNI_TRUE; 
	} 
	return UNI_FALSE; 
} 
UNI_BOOL CZsP2pBlock::CreateSendCanal(UNI_DWORD dwFileID,char *fileName,UNI_DWORD dwFileSize,char *toWho,char *pathName,UNI_DWORD dwSvrIp,UNI_WORD dwSvrPort) 
{ 
	HCANAL hsvr; 
	OBJECTINFO *pOld; 
	if(pOld=m_SendFiles.FindFile(dwFileID,toWho)) 
	{ 
		if(m_SendFiles.AddTail(pOld)) 
			return UNI_FALSE; 
		this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
		this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
		delete pOld; 
		return UNI_FALSE; 
	} 
	 
	if(hsvr=this->m_UDPCanal.CreateCanal(dwSvrIp,dwSvrPort)) 
	{ 
		if(pOld=new OBJECTINFO) 
		{ 
			this->InitializeFileInfo(pOld,dwFileID,dwFileSize,FILE_ACT_WAIT,toWho,fileName,hsvr);//不应是服务器的 
			if(pOld->pLastCmd=new UDPFILE_CMD) 
			{ 
				this->InitializeCmd(&pOld->pLastCmd->head,dwFileID,dwFileSize,0,toWho,UDP_CLIENT_HERE,pOld->myCanalId); 
				this->m_UDPCanal.Send(hsvr,pOld->pLastCmd,sizeof(pOld->pLastCmd->head)); 
				if(m_SendFiles.AddTail(pOld)) 
				{ 
					this->m_pEvent->UI_Initialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra,pathName); 
					return UNI_TRUE; 
				} 
				delete pOld->pLastCmd; 
			} 
			delete pOld; 
		} 
		this->m_UDPCanal.CloseCanal(hsvr); 
	} 
	return UNI_FALSE; 
} 
void CZsP2pBlock::DestorySendCanal(UNI_DWORD dwFileID, char *toWho) 
{ 
	OBJECTINFO *pOld; 
	if(pOld=this->m_SendFiles.FindFile(dwFileID,toWho)) 
	{ 
		this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
		DeleteFileInfo(pOld); 
	} 
} 
UNI_BOOL CZsP2pBlock::UserStartSend(UNI_DWORD dwFileID,char *toWho) 
{ 
	OBJECTINFO *pOld; 
	if(pOld=this->m_SendFiles.FindFile(dwFileID,toWho)) 
	{ 
		if(UNI_TRUE==this->m_SendFiles.AddTail(pOld)) 
		{ 
			if(pOld->pLastCmd=new UDPFILE_CMD) 
			{ 
				this->InitializeCmd(&pOld->pLastCmd->head, 
					pOld->BaseInfo.dwFileID, 
					pOld->BaseInfo.dwFileSize, 
					0, 
					toWho, 
					UDP_CLIENT_FILE_REQ, 
					pOld->myCanalId); 
				strncpy(pOld->pLastCmd->fileName,pOld->BaseInfo.fileName,sizeof(pOld->pLastCmd->fileName)); 
				pOld->pLastCmd->head.other_len =strlen(pOld->pLastCmd->fileName)+1; 
				this->m_UDPCanal.Send(pOld->hfrom,pOld->pLastCmd,sizeof(pOld->pLastCmd->head)+pOld->pLastCmd->head.other_len); 
				pOld->dwTickCount=UNI_GetTickCount(); 
				return UNI_TRUE; 
			} 
			 
		} 
		this->m_pEvent->UI_OnBadError(&pOld->BaseInfo); 
		this->m_pEvent->UI_UnInitialize(&pOld->BaseInfo,pOld->BaseInfo.pExtra); 
		DeleteFileInfo(pOld); 
	} 
	return UNI_FALSE; 
} 
 
void CZsP2pBlock::Close() 
{ 
#ifndef _DEBUG 
	m_bRuning=UNI_FALSE; 
#endif 
	if(this->m_WorkThread.IsCurrentThread()) 
	{ 
		this->m_WorkThread.Detach(); 
	} 
	else 
	{ 
		this->m_WorkThread.Join(); 
	} 
 
} 
/* 
 
void CZsP2pBlock::_Close(CZsP2pBlock* hP2p) 
{ 
	if(hP2p) 
	{ 
		hP2p->Close(); 
	} 
} 
*/ 
CZsP2pBlock* CZsP2pBlock::_Open(ZsP2pEventHandle  *pEvent,char *username,UNI_WORD dwLocalPort,UNI_DWORD dwLocalIp) 
{ 
	CZsP2pBlock *p2p; 
	if(p2p=new CZsP2pBlock ) 
	{ 
		if(!p2p->Open(pEvent,username,dwLocalPort,dwLocalIp)) 
		{ 
			delete p2p; 
			return UNI_NULL; 
		} 
	} 
	return p2p; 
} 
 
 
 
UNI_DWORD CZsP2pBlock::GetTransCount() 
{ 
	return this->m_SendFiles.GetCount()+this->m_recvFiles.GetCount(); 
}