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


// p2psvr.cpp : Defines the entry point for the console application. 
// 
 
//#include "stdafx.h" 
#include "stdio.h" 
#include "stdlib.h" 
//#define UNI_CURRENT_SYSTEM MS_WINDOWS 
#include "HMutex.h" 
#include "HList.h" 
#include "HUdpSock.h" 
#include "HTime.h" 
#include "HFile.h" 
#include "ZsProxySvr.h" 
#include "ZsP2pUserList.h" 
//#define MU_THREAD  
#define _TEST 1  
CHTime sys_time; 
struct P2P_SvrTask{ 
	UNI_DWORD dwTickCount; 
	P2P_SVRITEM user; 
	UDPFILE_CMD cmd; 
	UNI_DWORD   dwIP; 
	UNI_WORD	wPort; 
}; 
typedef CHList P2P_TaskList; 
 
#define MAX_USER_COUNT ((UNI_DWORD)-1) 
 
UNI_WORD m_port; 
 
CHUdpSock m_sock; 
 
CZsP2pUserList m_UserList; 
static UNI_DWORD m_MaxUserCount=MAX_USER_COUNT; 
 
P2P_TaskList m_tasks; 
 
P2P_TaskList::NODETYPE *FindTask(P2P_SVRITEM *pUser,UNI_DWORD dwFileID,char *sendName,char *recvName) 
{ 
	P2P_TaskList::NODETYPE *pNode; 
	P2P_TaskList::HLISTPOSTION pos; 
	if(pos=m_tasks.MoveToBegin()) 
	{ 
		while(pNode=m_tasks.MoveToNext(pos)) 
		{ 
			if(strcmp(pNode->user.userName,pUser->userName)==0 && 
				pNode->cmd.head.trans_id==dwFileID &&  
				strcmp(pNode->cmd.head.user_name,sendName)==0 && 
				strcmp(pNode->cmd.head.append_str,recvName)==0) 
			{ 
				return pNode; 
			} 
		} 
	} 
	return UNI_NULL; 
} 
 
void OnTestSvr(UDPFILE_CMD *pcmd) 
{ 
#ifdef _TEST 
	HFile file; 
	char buf[128]; 
//	if(file.OpenForAppend("c:\\p2p_svr_test.txt")) 
	{ 
		sprintf(buf,"%d\r\n",pcmd->head.trans_id); 
//		file.Write(buf,sprintf(buf,"%d\r\n",pcmd->head.trans_id)); 
//		file.Close(); 
		printf(buf); 
	} 
#endif 
} 
void OnClientQuit(UDPFILE_CMD *pcmd) 
{ 
	P2P_SVRITEM user; 
	P2P_TaskList::NODETYPE *pTask; 
	P2P_TaskList::HLISTPOSTION pos; 
 
	printf("received %s's QUIT_CMD [outip=%s outport=%d] [inip=%d inport=%d]\r\n",pcmd->head.user_name,HSocket::getipstr(pcmd->head.out_ip),pcmd->head.out_port, 
	       pcmd->head.use_ip,pcmd->head.use_port); 
	if(m_UserList.GetUserInfo(pcmd->head.user_name,&user)) 
	{ 
		if(pos=m_tasks.MoveToBegin()) 
		{ 
			while(pTask=m_tasks.MoveToNext(pos)) 
			{ 
				if(strcmp(pTask->user.userName,user.userName)==0) 
				{ 
					m_tasks.Remove(pTask); 
				} 
			} 
		} 
		m_UserList.RemovUser(pcmd->head.user_name); 
	}	 
} 
void OnClientHere(UDPFILE_CMD *pcmd) 
{ 
	/* 
	收到客户发来的报告位置的信息,建立客户信息 
	*/ 
	P2P_SVRITEM user,user2; 
	UDPFILE_CMD cmd; 
 
	printf("received %s's HERE_CMD [outip=%s outport=%d] [inip=%d inport=%d]\r\n", 
		pcmd->head.user_name,HSocket::getipstr(pcmd->head.out_ip),pcmd->head.out_port, 
	       pcmd->head.use_ip,pcmd->head.use_port); 
 
	user.dwTickCount=UNI_GetTickCount(); 
	user.outIp=pcmd->head.out_ip; 
	user.outPort=pcmd->head.out_port; 
	user.useIp=pcmd->head.use_ip; 
	user.usePort=pcmd->head.use_port; 
	strncpy(user.userName,pcmd->head.user_name,sizeof(user.userName)); 
 
	if(m_UserList.GetUserInfo(pcmd->head.user_name,&user2)==UNI_FALSE) 
	{ 
		if(m_UserList.GetUserCount()head.out_ip,pcmd->head.out_port); 
	printf("\t\treturn it!\r\n"); 
} 
void OnClientFileReq(UDPFILE_CMD *pcmd) 
{ 
	/* 
	收到发送方对接收方地址的请求 
	若查得接收方回答UDP_SVR_FILE_ACK,同时若是第一次对该任务的请求用UDP_SVR_FILE_REQ通知接收方 
	若十秒内未查到回答UDP_SVR_FILE_WAIT,超过十秒回答UDP_SVR_FILE_NO 
	*/ 
	P2P_SVRITEM user,user2; 
	UDPFILE_CMD cmd; 
	UNI_DWORD dwTickCount; 
	P2P_TaskList::NODETYPE *pTask; 
 
	printf("received %s's REQ_CMD [outip=%s outport=%d] [inip=%d inport=%d]\r\n",pcmd->head.user_name,HSocket::getipstr(pcmd->head.out_ip),pcmd->head.out_port, 
	       pcmd->head.use_ip,pcmd->head.use_port); 
 
	if((pcmd->head.other_len>1 ) && 
		 (pcmd->fileName[pcmd->head.other_len-1]==0) )//&& 
	{ 
		if(m_UserList.GetUserInfo(pcmd->head.user_name,&user))//找到发送方 
		{ 
			dwTickCount=UNI_GetTickCount(); 
 
			user.outIp=pcmd->head.out_ip; 
			user.outPort=pcmd->head.out_port; 
			user.useIp =pcmd->head.use_ip; 
			user.usePort=pcmd->head.use_port; 
			user.dwTickCount=dwTickCount; 
			 
			 
			memcpy(&cmd,pcmd,sizeof(cmd.head)); 
			cmd.head.other_len=pcmd->head.other_len>sizeof(cmd.fileName)?sizeof(cmd.fileName):pcmd->head.other_len; 
			strncpy(cmd.fileName,pcmd->fileName,cmd.head.other_len); 
			cmd.head.type=UDP_FILE_CMD; 
			cmd.head.user_data_len=0; 
 
			if(m_UserList.GetUserInfo(pcmd->head.append_str,&user2))//找到接收方 
			{ 
				printf("find recver: %s\n",user2.userName); 
				//创建或利用一个UDP_SVR_FILE_REQ任务 
				pTask=FindTask(&user2,pcmd->head.trans_id,pcmd->head.user_name,pcmd->head.append_str); 
				if(pTask==UNI_NULL) 
				{ 
					pTask=m_tasks.AddTail(); 
					pTask->dwTickCount=0; 
				} 
				if(pTask) 
				{ 
					//为接收方准备命令 
					memcpy(&pTask->user,&user2,sizeof(user2)); 
					memcpy(&pTask->cmd,&cmd,sizeof(pTask->cmd)); 
 
					//传递用户的出IP和端口 
					*((UNI_DWORD*)&pTask->cmd.fileName[cmd.head.other_len])=user2.outIp; 
					*((UNI_WORD*)&pTask->cmd.fileName[cmd.head.other_len+sizeof(user2.outIp)])=user2.outPort; 
					pTask->cmd.head.user_data_len =(sizeof(user2.outIp)+sizeof(user2.outPort)); 
 
					pTask->cmd.head.cmd=UDP_SVR_FILE_REQ; 
					pTask->cmd.head.type=UDP_FILE_CMD; 
 
					//通道号不能优化 
					pTask->cmd.head.out_ip=user.outIp; 
					pTask->cmd.head.out_port=user.outPort;//发送方通道号 
 
					cmd.head.out_ip=user2.outIp; 
					cmd.head.out_port=user2.outPort;//接收方通道号 
 
					////////为双方通信优化 
					if(pcmd->head.out_ip==user2.outIp) 
					{ 
						cmd.head.use_ip=user2.useIp; 
						cmd.head.use_port=user2.usePort; 
 
						pTask->cmd.head.use_ip=user.useIp; 
						pTask->cmd.head.use_port=user.usePort; 
 
						 
					} 
					else 
					{ 
						cmd.head.use_ip=user2.outIp; 
						cmd.head.use_port=user2.outPort; 
 
						pTask->cmd.head.use_ip=user.outIp; 
						pTask->cmd.head.use_port=user.outPort; 
					} 
 
					/////////////先回答发送方再通知接收方 
					cmd.head.cmd=UDP_SVR_FILE_ACK; 
					*((UNI_DWORD *)&cmd.fileName[cmd.head.other_len])=user.outIp; 
					*((UNI_WORD *)&cmd.fileName[cmd.head.other_len+sizeof(UNI_DWORD)])=user.outPort; 
					cmd.head.user_data_len=sizeof(UNI_DWORD)+sizeof(UNI_WORD); 
					m_sock.SendTo(&cmd,sizeof(cmd.head)+cmd.head.other_len+cmd.head.user_data_len,user.outIp,user.outPort); 
					printf("\t\tsend SVR_FILE_ACK to %s\r\n",user.userName); 
 
					////////////下面通知接收方/////////////////// 
					if(pTask->dwTickCount==0)//第一次收到该任务 
					{ 
						 
						m_sock.SendTo(&pTask->cmd,sizeof(pTask->cmd),user2.outIp,user2.outPort); 
 
						printf("\t\tsend SVR_FILE_REQ to %s\r\n",user2.userName); 
					} 
					pTask->dwTickCount=dwTickCount; 
				} 
				m_UserList.SetUser(&user); 
			} 
			else//未找到接收方 
			{ 
					cmd.head.cmd=UDP_SVR_FILE_WAIT; 
					if(pcmd->head.other_info!=0) 
					{ 
						if(dwTickCount < pcmd->head.other_info || 
							(dwTickCount-pcmd->head.other_info)>10000) 
							cmd.head.cmd=UDP_SVR_FILE_NO; 
 
						cmd.head.other_info=pcmd->head.other_info; 
					} 
					else 
						cmd.head.other_info =dwTickCount; 
					cmd.head.use_ip=cmd.head.out_ip=user.outIp; 
					cmd.head.use_port=cmd.head.out_port=user.outPort;//应答此处给出被应答客户的通道号 
					m_sock.SendTo(&cmd,sizeof(cmd),user.outIp,user.outPort);	 
			} 
		} 
	} 
} 
void OnClientAck(UDPFILE_CMD *pcmd) 
{ 
	/* 
	收到客户的ACK只能是由UDP_SVR_FILE_REQ引起的 
	*/ 
	P2P_SVRITEM user; 
	P2P_TaskList::NODETYPE *pTask; 
	printf("received %s's ACK_CMD [outip=%s outport=%d] [inip=%d inport=%d]\r\n",pcmd->head.user_name,HSocket::getipstr(pcmd->head.out_ip),pcmd->head.out_port, 
	       pcmd->head.use_ip,pcmd->head.use_port); 
//	if(true) 
	{ 
		if(m_UserList.GetUserInfo(pcmd->head.user_name,&user))//找到的是接收方的信息 
		{ 
 
			user.outIp=pcmd->head.out_ip; 
			user.outPort=pcmd->head.out_port; 
			user.useIp =pcmd->head.use_ip; 
			user.usePort=pcmd->head.use_port; 
			user.dwTickCount=UNI_GetTickCount(); 
 
			if(pTask=FindTask(&user,pcmd->head.trans_id,pcmd->head.append_str,pcmd->head.user_name)) 
			{ 
				printf("\t\tremove the task:sender=%s recver=%s filename=%s\r\n",pTask->cmd.head.user_name,pTask->cmd.head.append_str,pTask->cmd.fileName); 
				m_tasks.Remove(pTask); 
			} 
			m_UserList.SetUser(&user); 
		} 
	} 
} 
 
 
static UDP_SVRBUF m_cmd_buf; 
 
 
#ifdef MU_THREAD 
class MyProxy:public CZsProxySvr 
#else 
class MyProxy:public IZsProxySvr 
#endif 
{ 
	static void GetAddr(char *username,UNI_DWORD &ip,UNI_WORD &port) 
	{ 
		P2P_SVRITEM user; 
		ip=0; 
		port=0; 
		if(m_UserList.GetUserInfo(username,&user))//找到的是接收方的信息 
		{ 
			ip=user.outIp; 
			port=user.outPort; 
		} 
	} 
	virtual void SendTo(UDPFILE_CMD *pcmd) 
	{ 
		UNI_DWORD ip; 
		UNI_WORD port; 
		GetAddr(pcmd->head.append_str,ip,port); 
		if(ip!=0 && port!=0) 
		{ 
			pcmd->head.type=UDP_FILE_PROXY; 
			m_sock.SendTo(pcmd,pcmd->head.other_len+pcmd->head.user_data_len+sizeof(pcmd->head),ip,port); 
#ifdef _DEBUG 
			printf("PROXY:%s send pack to %s\n",pcmd->head.user_name,pcmd->head.append_str ); 
#endif 
		} 
	} 
}m_proxy; 
int main(int argc, char* argv[]) 
{ 
 
	 
	P2P_TaskList::NODETYPE *pTask; 
	P2P_TaskList::HLISTPOSTION pos; 
	UNI_DWORD dwTickCount; 
	HSocket::Initialize(); 
	(argc==2)?m_port=atoi(argv[1]):m_port=4096; 
	 
	if(UNI_FALSE==m_proxy.StartWork()) 
	{ 
		sys_time.GetCurTime(); 
		printf("p2p svr can not start proxy\r\n"); 
		return 0; 
	} 
	if(m_sock.CreateAt(m_port)) 
	{ 
		printf("%d year %d month %d day p2p svr start at port:%d\r\n",sys_time.GetYear(),sys_time.GetMonth(),sys_time.GetDay(),m_port); 
	} 
	else 
	{ 
		printf("p2p svr start failed at port:%d\r\n",m_port); 
		return 0; 
	} 
	while(1) 
	{ 
		if(m_sock.WaitForRead(0,10000)) 
		{ 
			if(dwTickCount=m_sock.RecvFrom(&m_cmd_buf.cmd,sizeof(m_cmd_buf),m_cmd_buf.cmd.head.out_ip,m_cmd_buf.cmd.head.out_port)) 
			{ 
				if(m_cmd_buf.cmd.head.other_len +m_cmd_buf.cmd.head.user_data_len+sizeof(m_cmd_buf.cmd.head)<=dwTickCount && 
					m_cmd_buf.cmd.head.type==UDP_FILE_CMD && 
					dwTickCount>=sizeof(m_cmd_buf.cmd.head) ) 
				{ 
					switch(m_cmd_buf.cmd.head.cmd) 
					{ 
					case UDP_CLIENT_HERE: 
						OnClientHere(&m_cmd_buf.cmd); 
						break; 
					case UDP_CLIENT_ACK: 
						OnClientAck(&m_cmd_buf.cmd); 
						break; 
					case UDP_CLIENT_FILE_REQ: 
						OnClientFileReq(&m_cmd_buf.cmd); 
						break; 
					case UDP_CLIENT_QUIT: 
						OnClientQuit(&m_cmd_buf.cmd); 
						break; 
					//////////////以下是代理命令///////////////////////////////////////// 
					case UDP_FILE_DATA: 
					case UDP_FILE_SEND_CANCEL: 
					case UDP_FILE_END: 
					case UDP_FILE_SUCCESS_ACK: 
					case UDP_FILE_NEXT: 
					case UDP_FILE_RECV_CANCEL: 
					case UDP_FILE_SUCCESS: 
					case UDP_READY_TEST: 
					case UDP_READY_OK: 
						m_proxy.AddToCmdList(&m_cmd_buf); 
						break; 
					default: 
					  printf("recv from:(%s,%d) cmd=%d\r\n",HSocket::getipstr(m_cmd_buf.cmd.head.out_ip), 
						  m_cmd_buf.cmd.head.out_port, 
						  m_cmd_buf.cmd.head.cmd,m_cmd_buf.cmd.head.other_len, 
						  m_cmd_buf.cmd.head.user_data_len, 
						  m_cmd_buf.cmd.head.type); 
					} 
				} 
				else if((m_cmd_buf.cmd.head.cmd==(UNI_WORD)UDP_COMMAND_TEST) && m_cmd_buf.cmd.head.type == (UNI_WORD)UDP_FILE_TEST) 
				{ 
					OnTestSvr(&m_cmd_buf.cmd); 
				} 
			} 
			else 
			  printf("bad recv from:(%s,%d) cmd=%d objlen=%d,userlen=%d type=%d\r\n", 
							HSocket::getipstr(m_cmd_buf.cmd.head.out_ip), 
							m_cmd_buf.cmd.head.out_port, 
							m_cmd_buf.cmd.head.cmd,m_cmd_buf.cmd.head.other_len,m_cmd_buf.cmd.head.user_data_len); 
		} 
		else 
		{ 
			dwTickCount=UNI_GetTickCount(); 
			//////////////////////////删除过期而没有任务的用户 
			m_UserList.DeleteUsers(30000,dwTickCount); 
		} 
		//////////////扫描任务,超时者删除,否则重发 
		dwTickCount=UNI_GetTickCount(); 
		if(pos=m_tasks.MoveToBegin()) 
		{ 
			while(pTask=m_tasks.MoveToNext(pos)) 
			{ 
				if(dwTickCountdwTickCount || (dwTickCount-pTask->dwTickCount)>10000) 
				{ 
					printf("time out delete stask sender=%s    recver=%s    filename=%s\r\n",pTask->cmd.head.user_name,pTask->cmd.head.append_str, 
					       pTask->cmd.fileName); 
					m_tasks.Remove(pTask); 
				} 
				else if((UNI_DWORD)(dwTickCount-pTask->dwTickCount)>1000 ) 
				{ 
					m_sock.SendTo(&pTask->cmd,sizeof(pTask->cmd),pTask->user.outIp,pTask->user.outPort); 
					printf("resend %s's $s REQ to %s\r\n",pTask->cmd.head.user_name,pTask->cmd.fileName,pTask->cmd.head.append_str); 
				} 
			} 
		} 
	} 
	return 0; 
}