Peercast核心代码执行流程

 Peercast核心代码执行流程

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值