转载请标明出处:http://www.cnblogs.com/zblade/

一、概要

  捣鼓UE4也有两个多月了,从这儿开始,逐步探究UE4中经典的值复制,RPC两种同步方式。想要弄到其复制和调用的原理,就得从根本的网络层开始捋,优秀的文章有:

风蚀之月-UE4网络底层概览-https://blog.ch-wind.com/ue4-network-overview/

知乎专栏-Exploring In UE4- https://zhuanlan.zhihu.com/p/34723199

  各位如果想大概了解网络的基本流程,可以认真学习一下这两篇文章,深入浅出讲解的很明晰。

  我也是在拜读了这几篇文章后,下定认真查看UE4的源码,从根本上了解UE4的网络原理,实现方案,优化方案等。

  整个系列应该比较长,就跟着自己的学习笔记,慢慢探究UE4的网络设计和实现,当作一个别样的旅程

二、基本网络类

  在游戏开发中,基本的网络都是通用的,来自于Socket, 在UE中,使用的是其子类BSDSocket(伯克利套接字),而对于BSDSocket的使用,又是封装在SocketSubSystem中,又在其基础上封装了一层SocketSubSystemModule来做模块管理。

  所以简单的总结,其基本的层次为:

    Socket->BSDSocket->SocketSubSystem->SocketSubSystemModule

  那么本文就介绍一下其基本的网络类,为后面的网络连接过程提供一个基本的知识印象。

2.1 基本网络类 Socket

  这个类是最基本的类,自然就是和网络最底层挂钩:IP 和 Port,主要用于实现对IP 和 port的连接,用于网络连接的绑定,监听,数据收发。

2.1.1 基本接口

  构建接口和析构函数:

	inline FSocket() :
		SocketType(SOCKTYPE_Unknown),
		SocketDescription(TEXT("")),
		IsNotSendEncrypt(false),
		IsNotRecvDecrypt(false)
	{ }

  其中SocketType分为三类: None/TCP/UDP, 多一嘴,UE是以UDP为主的。IsNotSendEncrypt/IsNotRecvDecrypt 为收发加密相关。

2.1.2 绑定相关接口

virtual bool Bind(const FInternetAddr& Addr) = 0;

virtual bool Connect(const FInternetAddr& Addr) = 0;

virtual bool Close() = 0;

2.1.3 数据接受相关接口

virtual bool SetReceiveBufferSize(int32 Size, int32& NewSize) = 0;

virtual bool Recv(uint8* Data, int32 BufferSize, int32& BytesRead, ESocketReceiveFlags::Type Flags = ESocketReceiveFlags::None)   

virtual bool RecvFrom(uint8* Data, int32 BufferSize, int32& BytesRead, FInternetAddr& Source, ESocketReceiveFlags::Type Flags = ESocketReceiveFlags::None)

2.1.4 数据发送相关接口

virtual bool SetSendBufferSize(int32 Size, int32& NewSize) = 0;

virtual bool SendTo(const uint8* Data, int32 Count, int32& BytesSent, const FInternetAddr& Destination);   

virtual bool Send(const uint8* Data, int32 Count, int32& BytesSent);  

   总结:这个类就是一个基类,大部分实现还是要看子类的override实现。

2.2 基本网络类 BSDSocket

  继承自Socket的类,相关接口实现更为完备,类似的类为FSocketBSDIPv6, 就在这儿一起处理了。

2.2.1 基本构造和析构接口

	FSocketBSD(SOCKET InSocket, ESocketType InSocketType, const FString& InSocketDescription, ISocketSubsystem * InSubsystem)
		: FSocket(InSocketType, InSocketDescription)
		, Socket(InSocket)
		, LastActivityTime(0)
		, SocketSubsystem(InSubsystem)
        , SendEncryptBufLength(DEFAULT_CRYPT_BUFFER_LEN)
        , RecvEncryptBufLength(DEFAULT_CRYPT_BUFFER_LEN)
	{
        SendEncryptBuf = new char[DEFAULT_CRYPT_BUFFER_LEN];
        RecvEncryptBuf = new char[DEFAULT_CRYPT_BUFFER_LEN];
    }

	/**
	 * Destructor.
	 *
	 * Closes the socket if it is still open
	 */
	virtual ~FSocketBSD()
	{
		Close();

        delete[] SendEncryptBuf;
        SendEncryptBuf = nullptr;
        delete[] RecvEncryptBuf;
        RecvEncryptBuf = nullptr;
	}

  比较简单,相对父类而言,多了收发buff的构建和析构回收操作。

2.2.2 其他接口

  也就是场景的数据收发,Bind, 连接,监听,Wait几个基本操作,也提供了多路操作。相对而言,重点关注几个变量:

   *  UpdateActivity() 这个函数用于更新最新的存活时间戳,应该是用于心跳检测相关的;

  *  FDateTime LastActivityTime: 最新的存活时间,用于心跳检测,同上;

  *  ISocketSubsystem* SocketSubsytem 注释中就说明了,只想创建其的SocketSubSystem, 所以BSDSocket的创建来自于SocketSubsystem的触发,后面会分析到。

2.2.3 具体的实现

  在对于的cpp中会有很多具体的实现,我就重点归纳几个要点:

  • Close: 内部会调用底层的closesocket来关闭socket
  • Bind: 内部会调用底层的bind来Bind socket
  • Connect: 同上,内部会调用底层的connect来connect socket
  • Listen: 调用底层的listen接口,返回bool表示是否在监听
  • SendTo: 如果发送的数据超过当前的buffer,会删除当前Buffer, 扩大2倍用来存储和加密数据, 然后执行发送操作sendto,如果发送数据量超过0,就默认为发送成功,刷新LastActivityTime
  • Send: 同上,只是调用的接口为send
  • RecvFrom: 接收接口,如果接收数据size超过当前Buffer,会删除当前buffer,扩大2倍用来存放接收的数据,对于接收到的数据,会进行是否接收数量(Byte)小于0且不为BLOCK状态,如果是则说明当前接收的数据不正确,返回。对于正确接受的数据,会进行解密操作,存放在对应Buffer中, 刷新LastActivityTime
  • Recv: 同上,只是调用的是recv接口,上面调用的是recvfrom接口,刷新LastActivityTime
  • GetConnectionState: 获取当前Socket的状态,根据LastActivityTime,如果当前连接正常,同时数据收发间隔超过5s,则判断是否需要重新刷新链接时间LastActivityTime,还是断开连接

  总结:这是项目中具体使用的BSDSocket,重点关注收发数据接口。   

2.3 基本网络类 SocketSubsystem

  前面介绍了Socket和BSDSocket,相当于介绍了工具,那么如何使用这个工具?UE给我们将这个工具做了一层封装,也就是SocketSubSystem,对于封装好的接口,我们想要调用,一般不会直接去调用,而是包装了一层,构建一个工具的管理器来进行相关的操作,避免和工具直接打交道。当然,UE还在SocketSubsystem的基础上更进一步的封装了Module来管理,后面会分析。

  在实际的项目中,SocketSubsystem只是一个积累,具体的SocketSubsystem,还需要根据对于的平台来进行创建,目前理出的主要的继承关系如下:

ISocketSubsystem---FSocketSubsystemBSDCommon---FSocketSubsystemBSD      ---FPS4SocketSubsystem
                                                                        ---FSwitchSocketSubsystem
                                                                        ---FSocketSubsystemWindows
                                                                        ---FSocketSubsystemLinux
                                                                        ---FSocketSubsystemMac
                                                                        ---FSocketSubsystemAndroid

                                            ---FSocketSubsystemBSDIPv6  ---FSocketSubsystemIOS
                                                                        ---FSocketSubsystemAndroidv6
                ---FSocketSubsystemSteam
                ---FSocketSubsystemHTML5

   基本关系:在游戏启动的时候,会先加载SocketSubsystemModule, 然后触发对应平台的SocketSubsystem的创建,再执行对应的BSDSocket的创建,所以接下来看看SocketSubsystemModule的加载过程。

2.4 基本网络类 SocketSubsystemModule的加载

  在游戏启动,或者编辑器启动的时候(注意编辑器下不是执行play,而是编辑器启动的时候),会执行Module的加载。在UE4中,各个模块都会统一到Module设计中,对应于网络这部分,就是SocketSubsystemModule,下面来逐步跟随追踪其加载过程:

2.4.1 加载FOnlineSubsystemModule

  首先会执行加载FOnlineSubsystemModule,在执行完该Module的加载后,会执行一次StartupModule(Module的虚函数接口,每个Module各自实现),在FOnlineSubsystemModule中实现为:

  在加载完成后,会执行GetOnlineSubsystem的操作:

  第一次加载的时候,OSSFactory为空,则会触发执行CreateSubsystem的操作:

  会在FOnlineFactoryNull中执行创建FOnlineSubsystemNull,然后执行初始化:

  初始化的关键是: new FOnlineIdentityNull的创建:

  里面会执行Login,而Login会进入到ISocketSubsystem:Get操作:

  最终来到了创建静态SocketSubsystem的操作:

  静态第一次创建的时候,执行加载SocketSubsystemModule,则其会执行:

  对应编辑器为Windows,则会执行:

  创建完后的register:

  总结:至此,完成了从FOnlineSubsystemModule的初始化,到SocketSubsystemModule的加载,然后完成SocketSubsystem的创建和注册的流程。

本文就写到这儿,主要分析了基本的网络类,网络system以及相关Module的加载,下一篇会重点分析NetDriver 和Connection 这两个UE中的重头类。

小白探究UE4网络系列(一)、UE4网络基础类分析的更多相关文章

  1. 探究UE4网络系列(二)、UE4网络核心类分析

    转载请标明出处:http://www.cnblogs.com/zblade/ 一.概要 前面分析了网络核心的基础类Socket/BSDSocket/SocketSubsystem/SocketSubs ...

  2. hdu5017:补题系列之西安网络赛1011

    补题系列之西安网络赛1011 题目大意:给定一个椭球: 求它到原点的最短距离. 思路: 对于一个椭球的标准方程 x^2/a^2 + y^2/b^2 +z^2/c^2=1 来说,它到原点的最短距离即为m ...

  3. Alamofire源码解读系列(七)之网络监控(NetworkReachabilityManager)

    Alamofire源码解读系列(七)之网络监控(NetworkReachabilityManager) 本篇主要讲解iOS开发中的网络监控 前言 在开发中,有时候我们需要获取这些信息: 手机是否联网 ...

  4. 恒天云技术分享系列6 – vLan网络原理解析

    转载自恒天云官网:http://www.hengtianyun.com/download-show-id-15.html Vlan网络模式优点 增加网络可扩展性 网络隔离,每个租户拥有独立的网络及vl ...

  5. 第三节,目标检测---R-CNN网络系列

    1.目标检测 检测图片中所有物体的 类别标签 位置(最小外接矩形/Bounding box) 区域卷积神经网络R-CNN 模块进化史 2.区域卷积神经网络R-CNN Region proposals+ ...

  6. 菜鸟系列docker——docker网络(8)

    Docker网络 Docker在容器内部运行应用,这些应用之间的交互依赖于大量不同的网络,这意味着Docker需要强大的网络功能. Docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多 ...

  7. 菜鸟系列Fabric——Fabric 网络架构介绍(4)

    Fabric 网络架构介绍 1. 网络架构介绍 如图所示,fabric网络架构主要包含客户端节点.CA节点.Peer节点.Orderer节点这几个部分.并且fabric架构是安装组织来进行划分当,每个 ...

  8. Docker系列02—Docker 网络模式

    一.Docker的四种网络模式 1.Docker 的四种网络模式: Bridge container 桥接式网络模式 Host(open) container 开放式网络模式 Container(jo ...

  9. windows网络服务之配置网络负载均衡(NLB)群集

    O首页51CTO博客我的博客 搜索 每日博报 社区:学院论坛博客下载更多            登录注册 家园 学院 博客 论坛 下载 自测 门诊 周刊 读书 技术圈 曾垂鑫的技术专栏 http:// ...

  10. iOS开发——网络实用技术OC篇&网络爬虫-使用青花瓷抓取网络数据

    网络爬虫-使用青花瓷抓取网络数据 由于最近在研究网络爬虫相关技术,刚好看到一篇的的搬了过来! 望谅解..... 写本文的契机主要是前段时间有次用青花瓷抓包有一步忘了,在网上查了半天也没找到写的完整的教 ...

随机推荐

  1. 转:java 看好的一些书

    地址 :  http://www.cnblogs.com/xrq730/p/4994545.html

  2. 吐血推荐珍藏的Visual Studio Code插件

    作为一名Java工程师,由于工作需要,最近一个月一直在写NodeJS,这种经历可以说是一部辛酸史了.好在有神器Visual Studio Code陪伴,让我的这段经历没有更加困难.眼看这段经历要告一段 ...

  3. Project Euler 52: Permuted multiples

    可以看到数字125874的两倍251748和它有着完全相同的数字,只是顺序不同而已.求一个最小的正整数\(x\),使得\(2x,3x,4x,5x,6x\)都有完全相同的数字. 分析:此题的思路比较直接 ...

  4. Css3动画-@keyframes与animation

    一.@keyframe 定义和用法 @keyframes是用来创建帧动画的,我们通过这个属性可以用纯css来实现一些动画效果. 一般格式是: @keyframes 动画名称{ 0%{ 动画开始时的样式 ...

  5. C表达式中的汇编指令

    C 表达式中的汇编指令 asm 为 gcc 中的关键字,asm 表达式为在 C代码中嵌套汇编指令,该表达式只是单纯的替换出汇编代码,并不对汇编代码的含义进行解析. asm 表达式有两种形式,第二种 a ...

  6. unittest加载测试用例名称必须以test开头,是否可以定制化

    ​ 前几天,在一个群里,一个人问了,这样一个问题.说他面试遇到一个面试官,问他,为啥unittest的测试用例要用test 开头,能不能定制化.他不知道为啥. 看到这个题目,我回答当然可以了,可以用l ...

  7. 连接xshell 时 连不上的问题

      最近这一周由于自己的xshell突然连接不到虚拟机,在网上找了很多种方法也没能解决,以至于自己在学习很多知识的时候都没能很好的去验证,去尝试.最后在求助大佬的时候终于将xshell重新连接到了虚拟 ...

  8. java-optional-快速使用-教程

    前言: 在公司中开发项目时碰到一个从Java8引入的一个Optional类,以前jdk版本使用的比较低,没有使用过,于是我在网上浏览了一些文档写篇文章学习总结一下,希望没有用过的朋友们都能够快速学习到 ...

  9. 【Vue | ElementUI】Vue离开当前页面时弹出确认框实现

    Vue离开当前页面时弹出确认框实现 1. 实现目的 在某种业务场景下,用户不允许跳转到其他页面.于是,需要在用户误操作或者是点击浏览器跳转时提示用户. 2. 实现原理 使用路由守卫beforeRout ...

  10. 附010.Kubernetes永久存储之GlusterFS超融合部署

    一 前期准备 1.1 基础知识 在Kubernetes中,使用GlusterFS文件系统,操作步骤通常是: 创建brick-->创建volume-->创建PV-->创建PVC--&g ...