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_)