執行的流程大致如下:
Peercast啟動時建立servMgr對象
servMgr啟動兩個伺服器線程,分別為servProc和idleProc
servProc啟動兩個監聽servent,分別用於監聽7144和7145連接埠
監聽servent啟動伺服器監聽線程Servent::servProc
當伺服器監聽線程監測到有新串連進入時,給這個串連分配新的servent
新的servent初始化串連資訊,並啟動incomingProc線程
incomingProc線程調用handshakeIncoming進行處理
handshakeIncoming讀取發送進來的請求,若為HTTP請求,則調用handshakeHTTP進行處理
handshakeHTTP處理HTTP請求,並做出相應的回複.其中若是頻道請求則調用handshakePLS進行處理,若是控制請求(ADMIN請求)則調用handshakeCmd進行處理,如果是播放請求則調用triggerChannel進行相應處理(此部分詳見播放模組分析)
WINDOWS程式都是從WinMain開始執行
int APIENTRY WinMain()
{
peercastInst = new MyPeercastInst();
peercastApp = new MyPeercastApp();
peercastInst->init();
}
// 整個程式的初始化,建立sys、servMgr和chanMgr對象以及從設定檔中讀取資訊
// sys、servMgr和chanMgr作為系統中三個最重要的全域變數,支撐起了Peercast核心代碼的大部分操作
// 其中sys用來提供底層操作,如建立SOCKET和擷取系統時間等,可理解為一個實現系統庫的類的對象
// servMgr用來管理網路傳輸,實現監聽、發送、接收資訊等功能,chanMgr用來實現對頻道的管理
void APICALL PeercastInstance::init()
{
sys = createSys();
servMgr = new ServMgr();
chanMgr = new ChanMgr();
//讀取設定檔中配置資訊
if (peercastApp->getIniFilename())
servMgr->loadSettings(peercastApp->getIniFilename());
servMgr->start();
}
// servMgr啟動兩個線程,其中serverProc(伺服器線程)監聽7144連接埠,處理進來的串連和發送資料
// idleProc在程式的空閑時間進行操作,如向YP發送資訊等
bool ServMgr::start()
{
serverThread.func = ServMgr::serverProc;
if (!sys->startThread(&serverThread))
return false;
idleThread.func = ServMgr::idleProc;
if (!sys->startThread(&idleThread))
return false;
return true;
}
//下面我們看看伺服器線程的執行情況
// --------------------------------------------------
// 啟動伺服器處理序,分配兩個servent,並初始化sock,預設serv監聽7144連接埠,serv2監聽7145連接埠
int ServMgr::serverProc(ThreadInfo *thread)
{
Servent *serv = servMgr->allocServent();
Servent *serv2 = servMgr->allocServent();
while (thread->active)
{
if (servMgr->autoServe)
{
if ((!serv->sock) || (!serv2->sock))
{
LOG_DEBUG("Starting servers");
{
Host h = servMgr->serverHost;
if (!serv->sock)
serv->initServer(h);
h.port++;
if (!serv2->sock)
serv2->initServer(h);
}
}
}else{
// stop server
serv->abort(); // force close
serv2->abort(); // force close
// cancel incoming connectuions
Servent *s = servMgr->servents;
while (s)
{
if (s->type == Servent::T_INCOMING)
s->thread.active = false;
s=s->next;
}
servMgr->setFirewall(ServMgr::FW_ON);
}
sys->sleepIdle();
}
sys->endThread(thread);
return 0;
}
//每個監聽的servent啟動一個監聽線程
// 啟動serverProc線程進行伺服器監聽
bool Servent::initServer(Host &h)
{
createSocket();
sock->bind(h);
thread.data = this;
thread.func = serverProc;
type = T_SERVER;
if (!sys->startThread(&thread))
throw StreamException("Can`t start thread");
return true;
}
//下面我們看看伺服器監聽線程是如何啟動並執行
int Servent::serverProc(ThreadInfo *thread)
{
Servent *sv = (Servent*)thread->data;
try
{
if (!sv->sock)
throw StreamException("Server has no socket");
sv->setStatus(S_LISTENING); //設定為監聽狀態
char servIP[64];
sv->sock->host.toStr(servIP); //servIP為"127.0.0.1:7144"
while ((thread->active) && (sv->sock->active()))
{
if (servMgr->numActiveOnPort(sv->sock->host.port) < servMgr->maxServIn)
{
ClientSocket *cs = sv->sock->accept(); //建立一個新的socket以接受串連
//迴圈判斷cs的值,若cs不為空白,則表示有新的串連進入
//這是非阻塞方式判斷是否有新串連的一種方法
if (cs)
{
LOG_DEBUG("accepted incoming");
Servent *ns = servMgr->allocServent(); //建立servent ns來處理串連請求
if (ns)
{
servMgr->lastIncoming = sys->getTime();
ns->servPort = sv->sock->host.port;
ns->networkID = servMgr->networkID;
ns->initIncoming(cs,sv->allow); //使用initIncoming處理髮送過來的資訊
}else
LOG_ERROR("Out of servents");
}
}
sys->sleep(100);
}
}catch(StreamException &e)
{
LOG_ERROR("Server Error: %s:%d",e.msg,e.err);
}
LOG_DEBUG("Server stopped");
sv->kill();
sys->endThread(thread);
return 0;
}
// 當監聽伺服器線程檢測到有新串連進入時,分配新的servent,並初始化Incoming,啟動線程調用incomingProc進行incoming的處理
void Servent::initIncoming(ClientSocket *s, unsigned int a)
{
try{
checkFree();
type = T_INCOMING;
sock = s;
allow = a;
thread.data = this;
thread.func = incomingProc;
setStatus(S_PROTOCOL);
char ipStr[64];
sock->host.toStr(ipStr);
LOG_DEBUG("Incoming from %s",ipStr);
if (!sys->startThread(&thread))
throw StreamException("Can`t start thread");
}catch(StreamException &e)
{
//LOG_ERROR("!!FATAL!! Incoming error: %s",e.msg);
//servMgr->shutdownTimer = 1;
kill();
LOG_ERROR("INCOMING FAILED: %s",e.msg);
}
}
// 調用handshakeIncoming進行Incoming的處理
int Servent::incomingProc(ThreadInfo *thread)
{
// thread->lock();
Servent *sv = (Servent*)thread->data;
char ipStr[64];
sv->sock->host.toStr(ipStr);
try
{
sv->handshakeIncoming();
}catch(HTTPException &e)
{
try
{
sv->sock->writeLine(e.msg);
if (e.code == 401)
sv->sock->writeLine("WWW-Authenticate: Basic realm=/"PeerCast/"");
sv->sock->writeLine("");
}catch(StreamException &){}
LOG_ERROR("Incoming from %s: %s",ipStr,e.msg);
}catch(StreamException &e)
{
LOG_ERROR("Incoming from %s: %s",ipStr,e.msg);
}
sv->kill();
sys->endThread(thread);
return 0;
}