raknet的线程模型。

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


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

#if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
	for (i=0; iIsBerkleySocket())
			((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 set
		rakPeer->quitAndDataEvents.WaitOnEvent(10);

	}

	rakPeer->isMainLoopThreadActive = false;

	return 0;

}

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

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



你可能感兴趣的:(raknet)