/******************************************************************************** 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; }
/************************************************* 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; }