ue4 网络代码分析

来源:互联网 发布:企业资本净额知乎 编辑:程序博客网 时间:2024/05/22 02:11

http://blog.csdn.net/xiaozhi0999/article/details/51326200


ue4实现了rpc,还是比较好用的,下面简单分析一下ue4网络部分的实现。

ue4中主要处理网络的类是UNetDriver, UNetDriver类中有如下两个成员

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. class UNetConnection* ServerConnection;  
  2. TArray<class UNetConnection*> ClientConnections;  

从名字就能看出ServerConnection代表了客户端向服务器建立的连接,而ClientConnections是服务器持有的客户端的连接。

ue4是通过UActorChannel来实现Actor在服务器和客户端之间同步的,其中每个需要在服务器和客户端之间同步的actor都会关联一个UActorChannel,我们看UNetConnection的代码可以验证这一点

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. TMap<TWeakObjectPtr<AActor>,class UActorChannel*> ActorChannels;  


看UActorChannel的实现,有如下几个重要的成员函数

发送数据:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. virtual FPacketIdRange SendBunch(FOutBunch* Bunch, bool Merge);  
  2. int32 SendRawBunch(FOutBunch* Bunch, bool Merge);  

接收数据:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. virtual void ReceivedBunch( FInBunch& Bunch ) PURE_VIRTUAL(UChannel::ReceivedBunch,);  
  2. bool ReceivedNextBunch( FInBunch & Bunch, bool & bOutSkipAck );  
  3. void ReceivedRawBunch( FInBunch & Bunch, bool & bOutSkipAck );  
  4. bool ReceivedSequencedBunch( FInBunch& Bunch );  

拿发送数据来说,UActorChannel中SendRawBunch实现还是调用UNetConnection中相应的函数,而在UNetConnection中,有如下成员变量

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. FBitWriter      SendBuffer;  
即发送缓冲区,SendRawBunch的主要作用就是把数据从FOutBunch中赋值到SendBuffer上,然后调用UNetConnection的LowLevelSend接口发送数据,当然,到最后还是调用Socket的Send函数发送缓冲区。

ps:以上讨论为了简化,忽略了类的层次(比如:UIpConnection从UNetConnection派生,所以有些函数具体实现是在UIpConnection中)


下面我们来具体分析一下rpc过程

当调用一个远端函数的时候,主要是在UNetDriver的InternalProcessRemoteFunction函数中处理的,先根据调用Actor来查找对应的UActorChannel,代码如下:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. UActorChannel* Ch = Connection->ActorChannels.FindRef(Actor);  

如果没有找到,则需要创建一个UActorChannel,如下:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. Ch = (UActorChannel *)Connection->CreateChannel( CHTYPE_Actor, 1 );  

注意, 对端主要是通过ChIndex来区分不同的Actor,所以需要为每个UActorChannel分配不同的ChIndex,这个过程是在CreateChannel中实现的,当不传递第三个参数的时候,如上边代码那样,会找到第一个可用的ChIndex,如下代码所示:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. // Search the channel array for an available location  
  2. for( ChIndex=FirstChannel; ChIndex<MAX_CHANNELS; ChIndex++ )  
  3. {  
  4.     if( !Channels[ChIndex] )  
  5.     {  
  6.         break;  
  7.     }  
  8. }  



0 0