Unity面试必备网络方面的干货知识

1.游戏客户端和服务端交换的两种方式

  1. 基于TCP的客户端-服务器通信

    • TCP(传输控制协议)提供可靠的、面向连接的数据传输。
    • 游戏客户端和服务端可以通过建立长连接的方式进行通信,实时发送和接收游戏数据。
    • TCP适用于需要保证数据完整性和可靠性的情况,但可能会引入一些延迟。
  2. 基于UDP的客户端-服务器通信

    • UDP(用户数据报协议)提供无连接的数据传输,不保证数据的可靠性和顺序性。
    • 在对实时性要求较高的游戏中,UDP通常被用于传输游戏数据,因为它的低延迟和快速传输特性。
    • 但是,UDP也需要额外的逻辑来处理丢包、重复包以及数据的顺序等问题。
  3. WebSocket

    • WebSocket是一种在单个TCP连接上进行全双工通信的协议,通常用于实时性要求较高的应用程序,如在线游戏。
    • 它通过HTTP协议进行握手,然后转换为WebSocket协议,使得客户端和服务器可以进行双向通信。
    • WebSocket适用于需要实时更新和交互的场景,如多人在线游戏

2.简单描述网络中的序列号概念

在网络通信中,序列号是指对数据包或消息进行排序的数字或标识符。序列号的目的是确保数据包按照正确的顺序到达目的地,并且检测和处理重复、丢失或乱序的数据包。

3.udp和tcp的区别

  1. 连接性:

    • TCP是面向连接的协议,通信前需要建立连接,然后进行数据传输,最后释放连接。这种连接是可靠的、全双工的,并且保证数据的顺序性和可靠性。
    • UDP是无连接的协议,通信不需要建立连接,数据包可以直接发送给目标地址。UDP不保证数据的可靠性和顺序性,因此通信速度更快,但数据可能会丢失或乱序。
  2. 可靠性:

    • TCP提供可靠的数据传输,通过序列号、确认和重传机制确保数据的完整性和可靠性,即使网络出现问题也会尝试重新传输数据,直到成功。
    • UDP不提供数据的可靠性保证,数据包发送后不会进行确认或重传,因此可能会丢失或者乱序。
  3. 通信方式:

    • TCP适用于需要稳定可靠传输的应用,如网页浏览、文件传输等,以及需要双向通信和流控制的场景。
    • UDP适用于对实时性要求较高、数据量较小、且能容忍少量数据丢失的应用,如音频/视频流、在线游戏等。
  4. 头部开销:

    • TCP的头部开销较大,包含了许多用于维护连接和可靠性的控制信息,因此传输的数据量相对较小,但相对稳定可靠。
    • UDP的头部开销较小,只包含了基本的信息,因此传输的数据量相对较大,但通信更加轻量级,速度更快。

4.tcp和ip协议栈各个层及分别的功能

  1. 应用层(Application Layer)

    • 应用层提供网络服务和应用程序之间的接口。它定义了不同应用之间的通信规则和数据交换格式。
    • 一些常见的应用层协议包括 HTTP、HTTPS、FTP、SMTP、POP3、IMAP、DNS 等。
  2. 传输层(Transport Layer)

    • 传输层提供端到端的数据传输服务。它负责在源主机和目标主机之间建立、维护和终止连接。
    • TCP 和 UDP 是传输层最常用的两种协议。TCP 提供可靠的、面向连接的数据传输服务,而 UDP 则提供不可靠的、无连接的数据传输服务。
  3. 网络层(Network Layer)

    • 网络层负责数据包的路由和转发,使得数据可以在不同的网络中进行传输。
    • IP(Internet Protocol)是网络层最核心的协议,它定义了数据包的格式、编址方式和路由选择算法,实现了主机之间的逻辑通信。
  4. 数据链路层(Data Link Layer)

    • 数据链路层负责在相邻节点之间传输数据。它将上层的数据分割成帧,并添加了控制信息和校验和,以确保数据的可靠传输。
    • 最常见的数据链路层协议包括以太网协议(Ethernet)、Wi-Fi 协议等。
  5. 物理层(Physical Layer)

    • 物理层负责在物理媒介上传输比特流,实现了电信号的编码、调制和解调,以及数据的传输和接收。
    • 物理层定义了硬件设备之间的连接方式和传输介质,如电缆、光纤、无线电波等。

5.在 C# 中,可以使用 System.Net.Http.HttpClient 类来执行 HTTP 请求,包括常见的 GET、POST、PUT、DELETE 等方法。以下是 C# 中常用的几个 HTTP 方法的示例代码:

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        // 创建 HttpClient 实例
        using (HttpClient client = new HttpClient())
        {
            // 发送 GET 请求
            HttpResponseMessage response = await client.GetAsync("https://api.example.com/data");
            if (response.IsSuccessStatusCode)
            {
                string content = await response.Content.ReadAsStringAsync();
                Console.WriteLine("GET 请求返回的数据:" + content);
            }
            else
            {
                Console.WriteLine("GET 请求失败:" + response.StatusCode);
            }

            // 发送 POST 请求
            var postData = new StringContent("{\"name\":\"John\",\"age\":30}", System.Text.Encoding.UTF8, "application/json");
            response = await client.PostAsync("https://api.example.com/resource", postData);
            if (response.IsSuccessStatusCode)
            {
                string content = await response.Content.ReadAsStringAsync();
                Console.WriteLine("POST 请求返回的数据:" + content);
            }
            else
            {
                Console.WriteLine("POST 请求失败:" + response.StatusCode);
            }

            // 发送 PUT 请求
            var putData = new StringContent("{\"name\":\"John\",\"age\":35}", System.Text.Encoding.UTF8, "application/json");
            response = await client.PutAsync("https://api.example.com/resource/123", putData);
            if (response.IsSuccessStatusCode)
            {
                Console.WriteLine("PUT 请求成功");
            }
            else
            {
                Console.WriteLine("PUT 请求失败:" + response.StatusCode);
            }

            // 发送 DELETE 请求
            response = await client.DeleteAsync("https://api.example.com/resource/123");
            if (response.IsSuccessStatusCode)
            {
                Console.WriteLine("DELETE 请求成功");
            }
            else
            {
                Console.WriteLine("DELETE 请求失败:" + response.StatusCode);
            }
        }
    }
}

6.如何区分消息类型,处理分包黏包,分包,黏包的概念

  1. 消息类型的区分

    • 在网络通信中,通常通过消息的头部信息来标识消息的类型。这些头部信息可以包括消息的长度、消息类型、数据校验和等信息。根据头部信息的不同,接收方可以识别出不同类型的消息,并进行相应的处理。
  2. 黏包(Packet Sticking):

    • 黏包是指多个消息或数据包被粘合在一起,形成一个大的消息,接收方在解析数据时无法准确地区分各个消息的边界。这种情况通常发生在发送方连续发送多个小消息,而接收方在一次性接收到多个消息时无法准确分割它们的情况下。
    • 黏包问题可能导致接收方无法正确解析消息,造成数据错误或丢失。
  3. 分包(Packet Splitting)

    • 分包是指一个消息或数据包被分割成多个部分进行传输,接收方在接收到这些部分时需要将它们重新组装成完整的消息。这种情况通常发生在消息的大小超过了网络传输的最大限制,需要进行分割才能发送的情况下。
    • 分包问题可能导致接收方无法正确组装消息,造成数据丢失或不完整。

为了解决分包和黏包问题,可以采取以下一些方法:

  • 消息长度标识:在消息的头部添加消息长度字段,接收方根据长度信息来准确地划分消息边界。
  • 消息分隔符:在消息的尾部添加特定的分隔符,用于标识消息的结束。接收方根据分隔符来分割消息。
  • 固定长度消息:规定每个消息的固定长度,即使消息内容不足,也要填充特定字符使其达到固定长度。
  • 消息头部信息:在消息的头部添加额外的信息,如消息类型、消息序号等,以便接收方准确识别消息。
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值