Advertisement

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

阅读量:

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

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

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

基于UDP的客户端-服务器通信

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

WebSocket

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

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

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

3.udp和tcp的区别

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

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

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

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

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

应用层(Application Layer)

复制代码
 * 应用层提供网络服务和应用程序之间的接口。它定义了不同应用之间的通信规则和数据交换格式。
 * 一些常见的应用层协议包括 HTTP、HTTPS、FTP、SMTP、POP3、IMAP、DNS 等。

传输层(Transport Layer)

复制代码
 * 传输层提供端到端的数据传输服务。它负责在源主机和目标主机之间建立、维护和终止连接。
 * TCP 和 UDP 是传输层最常用的两种协议。TCP 提供可靠的、面向连接的数据传输服务,而 UDP 则提供不可靠的、无连接的数据传输服务。

网络层(Network Layer)

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

数据链路层(Data Link Layer)

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

物理层(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);
    
         }
    
     }
    
     }
    
 }
    
    
    
    
    cs
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-19/udmTZzjN9wGI4LbxygDJ28Choc36.png)

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

消息类型的区分

复制代码
 * 在网络通信中,通常通过消息的头部信息来标识消息的类型。这些头部信息可以包括消息的长度、消息类型、数据校验和等信息。根据头部信息的不同,接收方可以识别出不同类型的消息,并进行相应的处理。

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

分包(Packet Splitting)

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

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

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

全部评论 (0)

还没有任何评论哟~