转载请标明出处: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. 【解决】Got permission denied while trying to connect to the Docker daemon socket at......dial unix /var/run/docker.sock: permission denied

    >>> 问题:搭建Portainer时,选择本地连接报错? >>>分析: 根据报错信息可知是权限问题. 可能原因一:使用了非root用户启用或连接docker &g ...

  2. 只需十四步:从零开始掌握Python机器学习(附资源)

    转载:只需十四步:从零开始掌握Python机器学习(附资源) Python 可以说是现在最流行的机器学习语言,而且你也能在网上找到大量的资源.你现在也在考虑从 Python 入门机器学习吗?本教程或许 ...

  3. pat 1054 The Dominant Color(20 分)

    1054 The Dominant Color(20 分) Behind the scenes in the computer's memory, color is always talked abo ...

  4. codeblocks 调试

    codeblocks 调试工具使用的注意事项: 1.codebloccks 调试,必须要在一个项目下才可以,也就是说“单独的文件是不能运行debug工具的” 2.项目的目录文件名必须是全英文,同时文件 ...

  5. poj 1001 求高精度幂(Java, BigDecimal, pow, hasNext, stripTrailingZeros, toPlainString)

    求高精度幂 Time Limit: 500MS   Memory Limit: 10000K Total Submissions: 180325   Accepted: 43460 Descripti ...

  6. nyoj 276-比较字母大小 (顺序比较, 逆序输出)

    276-比较字母大小 内存限制:64MB 时间限制:3000ms 特判: No 通过数:13 提交数:15 难度:1 题目描述: 任意给出两个英文字母,比较它们的大小,规定26个英文字母A,B,C.. ...

  7. iOS UIKit x Android Widget

    Android的事件回调Listener相当于iOS的delegate回调. Android的事件回调接口Listener相当于iOS的protocol回调协议. Android的UI容器(Adapt ...

  8. lldb调试使用python脚本问题总结

    lldb调试器可以使用python脚本实现功能增强,但也不是可以随心所欲的,在实际中有很多地方需要注意. 首先是对多线程环境调试使用python脚本,也要考虑python脚本有多线程安全,尤其是有许多 ...

  9. 关于element-ui级联菜单(城市三级联动菜单)和回显问题

    https://segmentfault.com/a/1190000020458087 这是我写的,可以去看看,希望对你们有帮助!!!

  10. electron——dialog(实现导出excel)

    背景 前端点击导出excel按钮后,请求完需要导出的数据后发送给主进程electron,由主进程保存到本地 dialog 显示用于打开和保存文件.警报等的本机系统对话框. dialog 模块提供了ap ...