raknet的线程模型。

来源:互联网 发布:真人白家乐软件开发 编辑:程序博客网 时间:2024/05/17 23:43

gdb运行一个最简单的raknet程序,断点以后,敲入 info threads,可以看到有三个线程在跑


除了线程1的主线程外,还有其他两个线程,干什么的呢?由于只调用了一个startup函数,进入startup函数发现如下代码

#if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)for (i=0; i<socketDescriptorCount; i++){if (socketList[i]->IsBerkleySocket())((RNS2_Berkley*) socketList[i])->CreateRecvPollingThread(threadPriority);}#endif

errorCode = RakNet::RakThread::Create(UpdateNetworkLoop, this, threadPriority);

这两处创建了线程。但是有一堆的现在条件,打调试信息,看看是否走到这里

在以上的语句中分别打入pritf语句后,在起程序,发现如下


可以看到.两个线程都被穿件,而且,如果监听多个端口的话,会起n+1个线程。下面来看看这些线程都干什么。

第一个线程的循环体

unsigned RNS2_Berkley::RecvFromLoopInt(void){isRecvFromLoopThreadActive.Increment();while ( endThreads == false ){RNS2RecvStruct *recvFromStruct;recvFromStruct=binding.eventHandler->AllocRNS2RecvStruct(_FILE_AND_LINE_);if (recvFromStruct != NULL){recvFromStruct->socket=this;RecvFromBlocking(recvFromStruct);if (recvFromStruct->bytesRead>0){RakAssert(recvFromStruct->systemAddress.GetPort());binding.eventHandler->OnRNS2Recv(recvFromStruct);}else{RakSleep(0);binding.eventHandler->DeallocRNS2RecvStruct(recvFromStruct, _FILE_AND_LINE_);}}}isRecvFromLoopThreadActive.Decrement();return 0;}

核心函数是RecvFromBlocking(recvFromStruct),看实现

void RNS2_Berkley::RecvFromBlockingIPV4(RNS2RecvStruct *recvFromStruct){sockaddr* sockAddrPtr;socklen_t sockLen;socklen_t* socketlenPtr=(socklen_t*) &sockLen;sockaddr_in sa;memset(&sa,0,sizeof(sockaddr_in));const int flag=0;{sockLen=sizeof(sa);sa.sin_family = AF_INET;sa.sin_port=0;sockAddrPtr=(sockaddr*) &sa;}recvFromStruct->bytesRead = recvfrom__( GetSocket(), recvFromStruct->data, sizeof(recvFromStruct->data), flag, sockAddrPtr, socketlenPtr );if (recvFromStruct->bytesRead<=0){return;}recvFromStruct->timeRead=RakNet::GetTimeUS();{recvFromStruct->systemAddress.SetPortNetworkOrder( sa.sin_port );recvFromStruct->systemAddress.address.addr4.sin_addr.s_addr=sa.sin_addr.s_addr;}// printf("--- Got %i bytes from %s\n", recvFromStruct->bytesRead, recvFromStruct->systemAddress.ToString());}

recvfrom__,阻塞函数。

可以猜测,这个线程是用来接收数据的,接收到以后放入一个队列中,然后通过一个事件,通知处理线程处理数据。


看看下一个线程的作用

RAK_THREAD_DECLARATION(RakNet::UpdateNetworkLoop){RakPeer * rakPeer = ( RakPeer * ) arguments;BitStream updateBitStream( MAXIMUM_MTU_SIZE#if LIBCAT_SECURITY==1+ cat::AuthenticatedEncryption::OVERHEAD_BYTES#endif);// rakPeer->isMainLoopThreadActive = true;while ( rakPeer->endThreads == false ){if (rakPeer->userUpdateThreadPtr)rakPeer->userUpdateThreadPtr(rakPeer, rakPeer->userUpdateThreadData);rakPeer->RunUpdateCycle(updateBitStream);// Pending sends go out this often, unless quitAndDataEvents is setrakPeer->quitAndDataEvents.WaitOnEvent(10);}rakPeer->isMainLoopThreadActive = false;return 0;}

核心函数 RunUpdateCycle(updateBitStream),看其实现

实现函数太负责,下篇分析



0 0