Example #1
0
/********************************************************************************
  Function:		AddClientChannel
  Description:	增加一个客户端
  Input:  		pszhost 主机地址	unDesPort 目的端口	pszBindIP 本地IP地址 可以是0 表示本机的任意IP	localport 本地端口 可以为0 系统自动分配
  Output:		pSocketChnl   成功返回通道指针 
  Return:  		       
  Note:					
  Author:        	CHC
  Date:				2010/08/31
********************************************************************************/
INT CNetService::AddClientChannel( const char *pszhost, UINT16 unDesPort,const char *pszBindIP, 
									UINT16 localport,enumNetProtocolType eProtocolType,  ISocketChannel** pSocketChnl)
{
	if ( m_bIsExit )
	{
		return ERROR_NET_UNKNOWN;
	}

	if ( !m_bIsInit )
	{
		return ERROR_NET_UNKNOWN;
	}

	CGSAutoMutex		GSAutoMutex(&m_GSMutex);

	// 为了区分协议栈和gsp,得这么写
	/*if (!g_clsLogPtr)
	{
	m_clsThreadDealNetEvent.SetLogPath( GetApplicationPath().c_str() );

	m_clsThreadDealNetEvent.m_clsThreadPool.SetLogInstancePtr( m_clsThreadDealNetEvent.GetLogInstancePtr());
	}*/

	if (true == m_clsThreadDealNetEvent.IfMaxChannelCount())
	{
		return ERROR_NET_MAX_CHANNEL_COUNT;//已达到最大连接数
	}

	if (pszhost == NULL)		
	{
		return ERROR_NET_PARAM_WRONG;
	}

	//建立socketchannel
	CSocketChannel *pclsSocketChnl = new CSocketChannel();//此指针保存到队列中,直到通道需要删除时才释放,比如程序退出,或者上层请求关闭通道
	if ( NULL == pclsSocketChnl )
	{
		// 没申请到内存
		return ERROR_NET_UNKNOWN;
	}
	pclsSocketChnl->SetLocalIPPort(pszBindIP, localport);
	pclsSocketChnl->SetReMoteIPPort(pszhost, unDesPort);
	pclsSocketChnl->SetNetProtocolType( eProtocolType );
	pclsSocketChnl->SetServerType( CLIENT );
	pclsSocketChnl->SetChannelType( COMM_CHANNEL );//客户端建立的都是通讯通道

	//建立basesocket
	CBaseSocket* pBaseSocket = NULL;//生命周期和pclsSocketChnl一样,
#if _WIN32
	if (eProtocolType == NET_PROTOCOL_TCP)
	{
		pBaseSocket = new CWinTcpSocket();
	}
	else
	{
		pBaseSocket = new CWinUdpSocket();

	}
#endif

#if _LINUX
	if (eProtocolType == NET_PROTOCOL_TCP)
	{
		pBaseSocket = new CLinuxTcpSocket();
	}
	else
	{
		pBaseSocket = new CLinuxUdpSocket();

	}
#endif

	if ( NULL == pBaseSocket )
	{
		// 没申请到内存
		return ERROR_NET_UNKNOWN;
	}

	pBaseSocket->SetBlockMode( m_clsThreadDealNetEvent.GetBlockMode() );
	m_clsClientChannel.SetLocalIPPort(pszBindIP, localport);
	m_clsClientChannel.SetReMoteIPPort(pszhost,unDesPort);


	//创建通道
	if (m_clsClientChannel.CreateChannel(pBaseSocket) != ERROR_BASE_SUCCESS)
	{
		//创建 通道失败
		pclsSocketChnl->CloseChannel();
		delete pclsSocketChnl;
		pclsSocketChnl = NULL;

		delete pBaseSocket;
		pBaseSocket = NULL;	

		char szRemoteIP[16]={0};
		UINT16 uiRemotePort = 0;
		char szLocalIP[16]={0};
		UINT16 uiLocalPort = 0;
		m_clsClientChannel.GetLocalIPPort(szLocalIP,uiLocalPort);
		m_clsClientChannel.GetReMoteIPPort(szRemoteIP,uiRemotePort);
		CTRLPRINTF( g_clsLogPtr,"创建通道失败传入通道参数,pszhost:%s, unDesPort:%u, pszBindIP:%s, localport:%u \n",pszhost, unDesPort,pszBindIP,localport );
		CTRLPRINTF( g_clsLogPtr,"创建通道失败客户端通道参数,szRemoteIP:%s, uiRemotePort:%u, szLocalIP:%s, uiLocalPort:%u \n",szRemoteIP, uiRemotePort,szLocalIP,uiLocalPort );
		return ERROR_NET_CREATE_CHANNEL_FAIL;
	}

	sockaddr_in struLocalAddr;
#if _WIN32
	INT32   iLocalAddrLen = sizeof(sockaddr_in);
#endif
#if _LINUX
	socklen_t   iLocalAddrLen = sizeof(sockaddr_in);
#endif
	getsockname( pBaseSocket->GetSocket(), (sockaddr*)&struLocalAddr, &iLocalAddrLen );
	pclsSocketChnl->SetLocalIPPort(inet_ntoa(struLocalAddr.sin_addr), (UINT16) ntohs(struLocalAddr.sin_port));

	//保存CBaseSocket
	pclsSocketChnl->SetCbaseSocketPoint(pBaseSocket);

	//将socketchannel存入vector容器
	m_clsThreadDealNetEvent.SaveSocketChannel(pclsSocketChnl);

	pclsSocketChnl->SetLogInstancePtr(m_clsThreadDealNetEvent.GetLogInstancePtr());

	CTRLPRINTF(m_clsThreadDealNetEvent.GetLogInstancePtr(), "通道%p创建成功, new socket %d, szRemoteIP:%s, \
		uiRemotePort:%u, szLocalIP:%s, uiLocalPort:%u\n ",pclsSocketChnl,pBaseSocket->GetSocket(),pszhost,unDesPort,
		inet_ntoa(struLocalAddr.sin_addr), (UINT16) ntohs(struLocalAddr.sin_port));

#if OPERATING_SYSTEM

	// select 什么都不需要做

#elif _WIN32

	//加入完成端口
	HANDLE hHandle = m_clsThreadDealNetEvent.AddToIoCompletionPort((HANDLE)pBaseSocket->GetSocket(), (DWORD)pclsSocketChnl->GetIOCPHandleData());
	if (hHandle == NULL)
	{
		pclsSocketChnl->CloseChannel();
		delete pclsSocketChnl;
		pclsSocketChnl = NULL;

		delete pBaseSocket;
		pBaseSocket = NULL;	
		CTRLPRINTF(m_clsThreadDealNetEvent.GetLogInstancePtr(), "通道%p加入完成端口失败, socket %d\n ",pclsSocketChnl,pBaseSocket->GetSocket());
		return ERROR_NET_CREATE_CHANNEL_FAIL;
	}
	//投掷第一次接收数据请求
	pclsSocketChnl->RecvData();

#else
	//linux

	//加入epoll
	m_clsThreadDealNetEvent.EpollCtrl( EPOLL_CTL_ADD,pBaseSocket->GetSocket(),pclsSocketChnl->GetEpollEvent());

	pclsSocketChnl->AddRefCount();

#endif
	//转换
	*pSocketChnl = (ISocketChannel*)pclsSocketChnl;


	return ERROR_BASE_SUCCESS;
}
Example #2
0
/*************************************************
  Function:      AddServerChannel 
  Description:   建立通讯通道,
  Input:  
  Output:         
  Return:         
  Note:			对于	
*************************************************/
INT CNetService::AddServerChannel(const char* pszBindIP, UINT16 unPort, 
					 enumNetProtocolType eProtocolType, ISocketChannel** pSocketChnl)
{
	CGSAutoMutex		GSAutoMutex(&m_GSMutex);

	if ( !m_bIsInit )
	{
		return ERROR_NET_UNKNOWN;
	}

	// 为了区分协议栈和gsp,得这么写
	/*if (!g_clsLogPtr)
	{
		m_clsThreadDealNetEvent.SetLogPath( GetApplicationPath().c_str() );

		m_clsThreadDealNetEvent.m_clsThreadPool.SetLogInstancePtr( m_clsThreadDealNetEvent.GetLogInstancePtr());
	}*/	


	if (true == m_clsThreadDealNetEvent.IfMaxChannelCount())
	{
		return ERROR_NET_MAX_CHANNEL_COUNT;//已达到最大连接数
	}
	
	if (unPort < 0) //绑定的IP为null时 表示绑定本机任意IP
	{
		return ERROR_NET_PARAM_WRONG;
	}

	//建立socketchannel
	CSocketChannel *pclsSocketChnl = new CSocketChannel();//此指针保存到队列中,直到通道需要删除时才释放.在~CNetInterfaceCommData(void)里释放
	
	if ( NULL == pclsSocketChnl )
	{
		return ERROR_NET_UNKNOWN;
	}
	
	//设置通道属性
	pclsSocketChnl->SetLocalIPPort(pszBindIP, unPort);
	pclsSocketChnl->SetServerType( SERVER );
	pclsSocketChnl->SetNetProtocolType( eProtocolType );
	pclsSocketChnl->SetChannelType( LISTEN_CHANNEL );//不管是UDP还是tcp 凡是AddServerChannel add的通道都认为是监听通道

	
	//建立basesocket
	CBaseSocket* pBaseSocket = NULL;//生命周期和pclsSocketChnl一样,
#if _WIN32
	if (eProtocolType == NET_PROTOCOL_TCP)
	{
		pBaseSocket = new CWinTcpSocket();
		
	}
	else
	{
		pBaseSocket = new CWinUdpSocket();
	}
#endif
#if _LINUX
	if (eProtocolType == NET_PROTOCOL_TCP)
	{
		pBaseSocket = new CLinuxTcpSocket();
	}
	else
	{
		pBaseSocket = new CLinuxUdpSocket();

	}
#endif

	if ( NULL == pBaseSocket )
	{
		if ( pclsSocketChnl )
		{
			pclsSocketChnl->CloseChannel();
			delete pclsSocketChnl;
			pclsSocketChnl = NULL;
		}
		return ERROR_NET_UNKNOWN;
	}
	 
	pBaseSocket->SetBlockMode( m_clsThreadDealNetEvent.GetBlockMode() );
	m_clsServerChannel.SetLocalIPPort(pszBindIP, unPort);
	//创建通道
	if (m_clsServerChannel.CreateChannel(pBaseSocket) != ERROR_BASE_SUCCESS)
	{
		//创建 通道失败
		pclsSocketChnl->CloseChannel();
		delete pclsSocketChnl;
		pclsSocketChnl = NULL;

		delete pBaseSocket;
		pBaseSocket = NULL;

		return ERROR_NET_CREATE_CHANNEL_FAIL;
	}


	//保存CBaseSocket
	pclsSocketChnl->SetCbaseSocketPoint(pBaseSocket);

	//将socketchannel存入vector容器
    m_clsThreadDealNetEvent.SaveSocketChannel(pclsSocketChnl);

	pclsSocketChnl->SetLogInstancePtr(m_clsThreadDealNetEvent.GetLogInstancePtr());

#if OPERATING_SYSTEM

	if (eProtocolType == NET_PROTOCOL_TCP)
	{
		pstruThreadPoolTask	 pTask = (pstruThreadPoolTask) malloc(sizeof(struThreadTask));//在任务结束时或程序退出时的在线程池的Uninitialize()中释放

		if ( NULL == pTask )
		{
			return ERROR_NET_UNKNOWN;
		}

		memset(pTask,0x0,sizeof(struThreadTask));
		pTask->pFunction = &CCommunicationManager::Listen;
		pTask->enumEvent = LISTEN;
		pTask->pObject = (CCommunicationManager*)&m_clsThreadDealNetEvent;
		pTask->pObject2 = pclsSocketChnl;
		m_clsThreadDealNetEvent.m_clsThreadPool.AssignTask(pTask);
		m_clsThreadDealNetEvent.m_clsThreadPool.WakeUpThread();

	}
	

#elif _WIN32
	
	if (eProtocolType == NET_PROTOCOL_UDP)
	{
		//加入完成端口
		m_clsThreadDealNetEvent.AddToIoCompletionPort((HANDLE)pBaseSocket->GetSocket(), (DWORD)pclsSocketChnl->GetIOCPHandleData());
		//发起接收
		pclsSocketChnl->RecvData();
	}
	else
	{
		//m_clsThreadDealNetEvent.m_clsThreadPool.AddThread(1);//增加一个线程去完成下面创建的任务,即监听

		pstruThreadPoolTask	 pTask = (pstruThreadPoolTask) malloc(sizeof(struThreadTask));//在任务结束时或程序退出时的在线程池的Uninitialize()中释放

		if ( NULL == pTask )
		{
			return ERROR_NET_UNKNOWN;
		}

		memset(pTask,0x0,sizeof(struThreadTask));
		pTask->pFunction = &CCommunicationManager::Listen;
		pTask->enumEvent = LISTEN;
		pTask->pObject = (CCommunicationManager*)&m_clsThreadDealNetEvent;
		pTask->pObject2 = pclsSocketChnl;
		m_clsThreadDealNetEvent.m_clsThreadPool.AssignTask(pTask);
		m_clsThreadDealNetEvent.m_clsThreadPool.WakeUpThread();
	}
	

#else	//linux
	
	if (eProtocolType == NET_PROTOCOL_UDP)
	{
		//加入EPOLL
		m_clsThreadDealNetEvent.EpollCtrl( EPOLL_CTL_ADD,pBaseSocket->GetSocket(),pclsSocketChnl->GetEpollEvent());

	}
	else
	{

		pstruThreadPoolTask	 pTask = (pstruThreadPoolTask) malloc(sizeof(struThreadTask));//在任务结束时或程序退出时的在线程池的Uninitialize()中释放

		if ( NULL == pTask )
		{
			return ERROR_NET_UNKNOWN;
		}

		memset(pTask,0x0,sizeof(struThreadTask));
		pTask->pFunction = &CCommunicationManager::Listen;
		pTask->enumEvent = LISTEN;
		pTask->pObject = (CCommunicationManager*)&m_clsThreadDealNetEvent;
		pTask->pObject2 = pclsSocketChnl;
		m_clsThreadDealNetEvent.m_clsThreadPool.AssignTask(pTask);
	}
#endif

	//转换
	*pSocketChnl = (ISocketChannel*)pclsSocketChnl;

	return ERROR_BASE_SUCCESS;
}