执行的流程大致如下:
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;
}