面试 7 真题

1, Socket粘包解包过程,传输数据的压缩是如何做的?

解决数据分包和粘包的基本策略如下

消息定长: 比如一个100,那么读取端每次读取数据就截取100个长度的数据,然后交给业务成去做解析

在消息尾部加一些特殊字符,那么在读取数据的时候,只要读取到这个特殊字符,就认为已经可以截取一个完整的数据包了.这种情况在一定的业务情况下实用.

读取缓存的数据时不定长的,所以我们把读取到的数据添加到我们自己的一个byte[]数组中,然后根据我们的业务逻辑来找到指定的特殊协议头部,协议长度,协议尾部,然后从我们byte[]中获取一个完整的数据包,然后在对数据包进行业务解析就可以得到正确结果.

Socket发送的内容是什么

发送内容可以是数字,字符串,或者是对象,但是他们在传输的过程中都将被转化为字节流

Socket的心跳实现是如何实现的

"心跳包"就是服务器端和客户端约定好的一种数据

所谓"心跳包"机制,其实就是服务器端按照固定的频率给客户端发送心跳包,客户端接受到心跳包之后做回应.如果服务器发送了一个心跳包,客户端没有回应,服务器认为客户端已经不再了.就回断开长连接

说明:服务器只是在客户端长时间没有给服务器发送数据的情况下,才会发送心跳包

客户端每隔一个时间间隔发送一个探测包给服务器

客户端发包时启动一个超时定时器

服务器端接收到检测包,应该回应一个包

如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器

如果客户端的超时定时器超时,依然没有收到应打包,则说明服务器挂了

如何实现断线重连

粗略的做法是,当客户端调用send或recv失败,然后WSAGetLastError()判断错误编号,然后关闭socket,在创建一个socket,然后进行connect操作.

正常操作:

客户端维护一个线程安全的待发送信息队列

开启死循环

判断Socket=null

调用Socket的sendUrgentData(OxFF)发送1个字节的心跳包

捕捉到连接异常后就关闭IO和Socket连接

读取队列内容,如果队列为空就休眠3秒,然后continue

遍历待发送消息队列,一次发送里面的内容

全部发送成功后清空队列

如果socket为null说明断开连接;重建socket连接,并开启IO

重建连接时如果连接不上,出现异常,那就休眠10秒,之后进入新一轮循环

TCP/IP,UDP实现有什么区别?HTTP有什么优势

TCP连接在客户端和服务端数据通信前,会进行三次确认才会正式建立连接,也即是三次握手.特点是面向连接,适合进行大数据量,持续连接的网络通讯,

UDP连接无连接,不需要确认连接,即可进行数据通信,特点是无连接,适合小数据量,高突发性,高频率的网络通信

AssetBundle 加载资源的过程是:

点了运行之后,将我在StreamAssets下生成的AB包Copy到C盘中的某个路径

开启更新模式 会从服务器下载一份file.txt和本地进行MD5的比对

若不一样会从服务器下载对应的MD5值文件 放到C盘 完成更新

然后启动框架,会调用Game的OninitOK方法

资源加载的方式都有哪些

1.Resource.load(string path)

优点: 同步 ,使用方便

缺点:只能加载Resource目录下的资源

2.WWW

优点:灵活,可以加载Application.streamingAssetsPath,Application.persistentDataPath目录下的资源,以及从网络上下载资源

缺点:异步,如果业务需要按需加载资源,容易打散逻辑

3.AssetBunlde.CreateFromFile(string path)

优点:同步,可以加载Application.persistentDataPath目录下的AssetBundle

缺点:AssetBundle不能压缩,在Android下不能加载Application.streamingAssetsPath下的AssetBundle

4, AssetBundle.CreateFromMemorylmmediate(byte[]bunary)

优点:同步,可以加载Application.persistentDataPath目录下压缩过的AssetBundle

缺点:在Andriid下不能加载Application.streamingAssetsPath下的AssetBundle

4,图集打包注意图集的大小和分辨率

5, NGUI和UGUI的区别?他们的适配都是如何去做的

UGUI的Canvas有世界坐标和屏幕坐标

UGUI的Image可以使用material

UGUI通过Mask来裁剪,而NGUI通过Panel的Clip

NGUI的渲染前后顺序是通过Widget的Depth,而UGUI的渲染顺序根据Hierarchy的顺序,越下面渲染在顶层

UGUI不需要绑定Colliders,UI可以自动拦截事件

UGUI的Anchor是相对父对象,没有提供高级选项,个人感觉UGUI的Anchor操作起来比NGUI更方便

UGUI没有Atlas一说,使用Sprite Packer

UGUI的Navigation在Scene中能可视化

UGUI的事件需要实现事件系统的接口,但写起来也算简单

Lua和C#是如何调用的,

Lua调用C#:

1.判断其实否注册       2. 生成(点击Lua->Clear wrap files->确定)  

如果一个c#方法要被Lua调用,则首先需要将其注册到Lua虚拟机中(LuaState.RegisterFunction),之后再Lua中就可以通过注册的名称来调用这个C#方法

2. 如果C#要调用Lua中的函数,则:

首先要在Lua虚拟机中加载该函数(LuaState.Dofile)

拿到目标函数(LuaState.GetFunction)

执行目标函数(LuaFunction.Call)

C#调用lua

C#通过Pinvoke方式调用了lua的dll(一个c库),然后这个dll执行了lua脚本

Lua的优化有哪些

使用局部变量 

预设物的优点有哪些

在游戏运行时实例化,Prefab相当于一个模板,对你已有的素材,脚本,参数,做一个默认配置,以便于以后修改,同时prefab打包的内容简化了导出的操作,便于团体的交流

当你场景中有大量相似的物体.如游戏中的小怪时就可以用frefab来对这些物体进行统一管理,这样当你需要修改物体属性时,只要修改一个物体,然后apply给prefab其他的物体也就一起改好了.还有当你需要用代码动态创建物体是也是用prefab的

ArrayList和List有何区别

在声明List集合时,我们需要为其声明List集合内数据的对象类型

而ArrayList会把所有插入的数据都当做object来处理

ArrayList存在不安全类型

装箱拆箱操作

请描述Interface与抽象类之间的区别

接口不是类,不能实例化,抽象类可以间接实例化

接口是完全抽象,抽象类为部分抽象

接口可以多继承  抽象类是单继承

线程和协程之间有何区别

多线程程序同时运行多个线程,而在任一指定时刻只有一个协程在运行,并且这个正在运行的协同程序只在必要时才被挂起.除主线程之外的线程无法访问Unity的对象,组件,方法.

unity没有多线程的概念,不过unity也给我们提供了StartCoroutine(协同程序)和LoadLevelAsync(异步加载关卡)后台加载场景的方法.

所谓协同:就是当你在StartCoroutine的函数体里处理一段代码时,利用yield语句等待执行结果,这期间不影响主程序的继续执行,可以协同工作.而LoadLevelAsync则允许你再后台加载新资源和场景,所以在利用协同,你就可以前台用loading条或动画提示玩家游戏未卡死,同时后台协同处理加载的事宜.

值类型和引用类型的区别

区别:值类型存储在内存栈中,引用类型数据存储在内存堆中,而内存单元中存放的是堆中存放的地址.

值类型存取快,引用类型存取慢

值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针和引用.

栈的内存是自动释放,堆内存是.NET中会由GC来自动释放

值类型继承自System.ValueType,引用类型继承自System.Object.

委托和事件有何区别

委托允许直接通过委托去访问相应的处理函数,而事件只能通过公布的回调函数去调用

事件只能通过"+=""-="方式注册和取消注册处理函数,而委托除此之外还可以使用"="直接赋值处理函数.事件只能在当前定义的类结构中调用,不能再外部调用.  

如何去掉敏感字

string s = "坏蛋"

s.Replace("坏蛋","**")

猜你喜欢

转载自blog.csdn.net/qq_41764460/article/details/81699410