localserver.cpp
来自「mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体」· C++ 代码 · 共 401 行
CPP
401 行
#include "stdafx.h"
#include "LocalServer.h"
#include "ChannelMenu.h"
#if USE_NAT
#include "../../natproxy/Client/nsvrctrl.h"
#endif
#pragma comment(lib, "Ws2_32.lib")
CLocalServer* CLocalServer::m_pLocalServer = NULL;
extern volatile HWND g_hMainWnd;;
// { Implementation of CLocalServer
DWORD WINAPI CLocalServer::_ConnectProc(LPVOID lpParam)
{
CLocalServer *pLocalServer = (CLocalServer *)lpParam;
assert(pLocalServer);
sockaddr saddr;
int iSize = sizeof(saddr);
SOCKET Sock;
while( (Sock = accept(pLocalServer->m_ListenSocket, &saddr, &iSize)) != INVALID_SOCKET )
{
if(!pLocalServer->AddChannel(Sock))
{
assert(0);
}
}
CloseHandle(pLocalServer->m_hConncetThread);
pLocalServer->m_hConncetThread = NULL;
return 0;
}
CLocalServer::CLocalServer()
: m_ThreadRef(0), m_uChlCounter(0), m_ListenSocket(INVALID_SOCKET),
m_ErrMsgID(0), m_bConnStop(false), m_hConncetThread(NULL)
{
}
CLocalServer::~CLocalServer()
{
// Stop();
}
CLocalServer *CLocalServer::CreateInstance()
{
if(m_pLocalServer == NULL)
{
m_pLocalServer = new CLocalServer();
}
return m_pLocalServer;
}
void CLocalServer::DeleteInstance()
{
if(m_pLocalServer)
{
delete m_pLocalServer;
m_pLocalServer = NULL;
}
}
void CLocalServer::HandleLocalSrvNotify(WPARAM wparam, LPARAM lparam)
{
switch(wparam)
{
case CASE_THREAD_EXIT:
assert(m_ThreadRef != 0);
if(m_ThreadRef == 0)
FireExit();
m_ThreadRef --;
if(m_ThreadRef == 0)
FireExit();
break;
}
}
void CLocalServer::FireExit()
{
if(m_ThreadRef == 0)
PostMessage(g_hMainWnd, WM_EXIT_EX, 0, 0);
}
#if USE_NAT
#define SERVICE_FILENAME "service.exe"
BOOL CLocalServer::InitNatProxy()
{
STARTUPINFO si;
PROCESS_INFORMATION pi ;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
char apppath[0xff];
::GetModuleFileName(NULL, apppath, 0xff);
char* p = apppath;
while(strchr(p, '\\'))
{
p = strchr(p, '\\');
p++;
}
*p = '\0';
strcat(apppath, SERVICE_FILENAME);
if (CreateProcess(apppath, NULL, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,
NULL, NULL, &si, &pi))
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return TRUE;
}
return FALSE;
}
BOOL CLocalServer::ExitNatProxy()
{
NSvrCtrl nsc;
nsc.Exit();
Sleep(10); // wait udp send
return TRUE;
}
#endif
#define MSGLIFETIME 5
BOOL CLocalServer::Run()
{
#if USE_NAT
InitNatProxy();
#endif
m_ErrMsgID = m_MsgMgr.CreateMsgID(MSGLIFETIME);
if(!InitNetWork())
{
assert(0);
m_MsgMgr.DeleteMsgID(m_ErrMsgID);
return FALSE;
}
else
{
sockaddr_in LocalAddr;
memset(&LocalAddr, 0, sizeof(LocalAddr));
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_port = htons(short(LOCALSERVERPORT));
char sLocalName[MAX_PATH] = "";
gethostname(sLocalName, sizeof(sLocalName));
hostent *ht = gethostbyname(sLocalName);
char *sIP = inet_ntoa((*(struct in_addr *)*ht->h_addr_list));
LocalAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(bind(m_ListenSocket, (sockaddr*)&LocalAddr, sizeof(sockaddr)) != 0)
{
WSACleanup();
return FALSE;
}
if(listen(m_ListenSocket, MAX_PENDING_SOCKET) != 0)
{
WSACleanup();
return FALSE;
}
if(NULL == (m_hConncetThread = CreateThread(NULL, 0, _ConnectProc,
(LPVOID)this, 0, &m_dwConnectThreadID)))
{
WSACleanup();
return FALSE;
}
return TRUE;
}
}
void CLocalServer::Stop()
{
if( INVALID_SOCKET != m_ListenSocket )
{
closesocket(m_ListenSocket);
m_ListenSocket = INVALID_SOCKET;
}
if( m_hConncetThread )
{
if( WaitForSingleObject(m_hConncetThread, 3000) != WAIT_OBJECT_0 )
{
TerminateThread(m_hConncetThread, 0);
m_hConncetThread = NULL;
}
}
ChannelMap::iterator itr = NULL;
for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
{
CChannelMgr::Dellocator(itr->second, TRUE);
}
m_ChannelMap.clear();
#if USE_NAT
ExitNatProxy();
#endif
m_MsgMgr.DeleteMsgID(m_ErrMsgID);
m_ErrMsgID = 0;
WSACleanup();
}
BOOL CLocalServer::AddChannel(SOCKET Sock)
{
assert(INVALID_SOCKET != Sock);
m_uChlCounter += 1;
CHANNELID ChannelID = m_uChlCounter;
CChannelMgr *pChannelMgr = CChannelMgr::Allocator(ChannelID);
if(!pChannelMgr->Init(Sock))
{
CChannelMgr::Dellocator(pChannelMgr);
assert(0);
return FALSE;
}
CAutoLock lock(&m_MapCritSec);
m_ChannelMap.insert(ChannelMap::value_type(ChannelID, pChannelMgr));
CChannelMenu::GetInstance()->SetChannelRunning(TRUE);
return TRUE;
}
void CLocalServer::DeleteChannel(CHANNELID ChannelID)
{
ChannelMap::iterator itr = NULL;
CAutoLock lock(&m_MapCritSec);
for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
{
if(ChannelID == itr->first)
{
CChannelMgr *pChannelMgr = itr->second;
if(pChannelMgr->DeadforFatalError()) //将最终的一条错误信息加进localserver
{
CString strRet, strRetErr;
pChannelMgr->GetChannelName(strRet);
CChannelMgr::HandleLayerErrCode(pChannelMgr->GetErrorCode(), strRetErr);
strRet += strRetErr;
m_MsgMgr.UpdateMessage(m_ErrMsgID, strRet, CMsgMgr::FORCESHOW | MSGLIFETIME);
}
m_ChannelMap.erase(itr);
CChannelMgr::Dellocator(pChannelMgr);
break;
}
}
if(m_ChannelMap.empty())
CChannelMenu::GetInstance()->SetChannelRunning(FALSE);
}
UINT CLocalServer::GetChannelNum()
{
CAutoLock lock(&m_MapCritSec);
UINT uChannelNum = (UINT)m_ChannelMap.size();
return uChannelNum;
}
void CLocalServer::GetChannelIDArray(CHANNELID *pChannelIDArray)
{
int i = 0;
ChannelMap::iterator itr = NULL;
CAutoLock lock(&m_MapCritSec);
for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
{
*(pChannelIDArray+i) = itr->first;
i++;
}
}
void CLocalServer::GetChannelMgrArray(CChannelMgr* pChannelMgrArray[])
{
int i = 0;
ChannelMap::iterator itr = NULL;
CAutoLock lock(&m_MapCritSec);
for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
{
pChannelMgrArray[i] = itr->second;
i++;
}
}
void GetChannelName(CHANNELID ChannelID);
CChannelMgr *CLocalServer::GetChannelMgr(CHANNELID ChannelID)
{
ChannelMap::iterator itr = NULL;
CAutoLock lock(&m_MapCritSec);
for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
{
if(ChannelID == itr->first)
{
return itr->second;
}
}
return NULL;
}
void CLocalServer::UpdateNoChannelMsg()
{
MultiLanguage LangDll;
CString strChl;
strChl = LangDll.GetStringByStr(_T("当前没有频道"));
m_MsgMgr.UpdateMessage(m_ErrMsgID, strChl, CMsgMgr::FORCESHOW | MSGLIFETIME);
}
void CLocalServer::UpdateLayer1Notify(WPARAM wparam, LPARAM lparam)
{
CHANNELID chlID = HIWORD(wparam);
UINT16 RetType = LOWORD(wparam);
CChannelMgr* pMgr = GetChannelMgr(chlID);
CString strRet;
if(pMgr)
{
pMgr->GetChannelName(strRet);
}
MultiLanguage LangDll;
int RetTypeOrigin = (SHORT) RetType ;
switch(RetTypeOrigin)
{
case PNT_CANNOT_LOGON_TS:
strRet += LangDll.GetStringByStr(_TEXT("无法登陆服务器,可能是服务暂时停止,或者是本台机器的防火墙在捣乱。"));
break;
case PNT_NO_CP:
strRet += LangDll.GetStringByStr(_TEXT("没有数据服务器,请联系服务商。"));
break;
case PNT_CHNL_CLOSED:
strRet += LangDll.GetStringByStr(_TEXT("此频道已经关闭,清尝试其他打开的频道。"));
break;
case PNT_NO_SUCH_RES:
strRet += LangDll.GetStringByStr(_TEXT("服务器上没有这个频道,请确认你打开的URL或者GTV文件是最新的。"));
break;
case PNT_CHNL_ENDED:
strRet += LangDll.GetStringByStr(_TEXT("此频道到此结束,谢谢观看。"));
break;
case PNT_LOW_VERSION:
strRet += LangDll.GetStringByStr(_TEXT("您使用的是旧版客户端,请到www.Openmysee.com下载最新版的客户端。"));
break;
case PNT_DISK_ERR:
strRet += LangDll.GetStringByStr(_TEXT("将数据写入磁盘时出错,请检查是否磁盘已满。"));
break;
default:
strRet += LangDll.GetStringByStr(_TEXT("未知类型的错误,请重新播放此频道!"));
break;
}
m_MsgMgr.UpdateMessage(m_ErrMsgID, strRet, CMsgMgr::FORCESHOW | MSGLIFETIME, CMsgMgr::MSGLV_WARNING);
}
CMsgMgr* CLocalServer::GetMsgMgr()
{
return &m_MsgMgr;
}
BOOL CLocalServer::InitNetWork()
{
WSADATA WsaData;
if(WSAStartup(MAKEWORD(2, 2), &WsaData) != 0)
return FALSE;
if(LOBYTE(WsaData.wVersion) != 2 || HIBYTE(WsaData.wVersion) != 2)
{
WSACleanup();
return FALSE;
}
m_ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
if(INVALID_SOCKET == m_ListenSocket)
{
WSACleanup();
return FALSE;
}
return TRUE;
}
// Implementation of CLocalServer }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?