UE4.27, 揣摩源码, 网络同步 (一) 初始化,握手,登录

0.  计算机网络常识回顾

  0.1. 四大层级,Socket抽象层

    应用层->传输层->网络层->网络接口层

    实际应用中,当我们使用socket技术后,关心的抽象是这样的

      红绿分别代表服务器客户端

      应用层<-Socket抽象层->传输层<->...<->传输层<-Socket抽象层->应用层

      应用层<-Socket抽象层->应用层

    可以看出,Socket是一种层级极高的抽象层

    它起源自UNIX系统,也承接了它们的文件哲学

    因此socket的接口使用起来有一种,是在对文件操作的恍惚感,比如read(),write(),close()

    win里通常是用send, recv替代write, read

    网络操作和文件操作本质上都有一个缓冲池的环节,不过socket把深层的通常不需要客制化的细节藏起来了

  0.1. Socket基本接口

    服务器Server

      初始化套接字   socket(传输层协议, 网络层协议)

      绑定IP与端口   bind(IP:PORT)

      监听       listen(...)

      接受连接     accept(...)

      send(), recv()

      close()     

    客户端Client
      初始化套接字   socket(传输层协议, 网络层协议)

      发起连接     connect(...)

      send(), recv()

      close()      

      

1.  Socket初始化

  1.1. SVO

    UIpNetDriver获得套接字子系统,籍此创建平台特化的基本socket,然后经有InternalBSDSocketFactory创建最终的FSocket

    (此套接字子系统不是单例模式里的那种gis子系统,看起来是个接口类,由loadmodule获得)

  1.2. 堆栈调用

    CreateAndBindSocket(...)

      CreateSocketForProtocol(...)

        CreateUniqueSocket(...)

          FSocketSubsystemWindows::CreateSocket(...)

          // 因平台特化

            FSocketSubsystemBSD::CreateSocket(SocketType, SocketDescription, ProtocolType)

              socket(af, type, protocal)

              //windows的平台socket,需要指定

              //  af        -[address_family]   AF_INET/AF_INET6    地址族, ipv4,ipv6...

              //  type    -[socket_type]        Stream/Datagram/RAW  套接字类型, 流式, 数据报式, 原始式

              //  protocal   -[protocal]       TCP/UDP        传输协议tcp,udp,idp,rdp...

              //反直觉的是,参数"报文类型"ProtocolType最终指定 [地址族af]

              //而参数"套接字类型"SocketType最终指定了 [套接字类型type] 和 [传输协议protocal]

              InternalBSDSocketFactory()

              //将socket转化为ue的FSocket

              //SocketDescription参数作为调试信息

  1.3. Socket部分总结

    服务器和客户端的连接采用的是socket抽象层

    不论是哪个平台,哪个底层协议,ue都已经在onlinesubsystem包装好了,我们不再特别关心

2.  简单介绍握手和登录

  2.1. 笔力有限,这几篇随笔着重于讨论网络同步的部分,至于前面的步骤,初始化 握手 登录,我们在此简单介绍

    2.1.1. 初始化

      // 初始化双端Socket并开始握手

      2.1.1.1. 服务器

        World持有NetDriver

          NetDriver持有Socket

             bind(作用上看,其实是等待UDP握手)

          NetDriver持有Connectionless

            Connectionless持有PacketHandler

      2.1.1.2. 客户端:

        PendingNetGame持有NetDriver

          NetDriver持有NetConnection
          NetDriver持有Socket

            NetConnection接手Socket

            NetConnection持有PacketHandler

              PacketHandler开始握手

    2.1.2. 握手
      // 握手是为了确认连接的可靠性,最终让服务端为客户端创建UNetConnection
        客户端  ->  HandShakeBegin         ->  服务端
        客户端  <-  ConnectChallenge       <-  服务端
        客户端  ->  ChallengeResponse     ->  服务端
        客户端  <-  ConnectChallengeAck    <-  服务端

        服务端为客户端创建NetConnection

 

    2.1.3. 登录
      // 在连接中进行登录流程

      // 登录最后,客户端加载map并将NetDriver移交给World

      // 登录最后,服务端将创建一个客户端的PlayerController
        客户端  ->  NMT_Hello       ->  服务端
        客户端  <-  NMT_Challenge      <-  服务端
        客户端  ->  NMT_Login      ->  服务端
        客户端  <-  NMT_Welcome    <-  服务端
        客户端  ->  NMT_Netspeed    ->  服务端

        // 客户端LoadMap
        客户端  ->  NMT_Join        ->  服务端

        // 服务端SpawnPlayActor

posted @ 2025-01-05 19:30  在找饭吃的陈  阅读(39)  评论(0)    收藏  举报