[Unity3d] 网络开发基础【个人复习笔记/有不足之处欢迎斧正/侵删】

本文主要是介绍[Unity3d] 网络开发基础【个人复习笔记/有不足之处欢迎斧正/侵删】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

TCP/IP

TCP/IP协议是一 系列规则(协议)的统称,他们定义了消息在网络间进行传输的规则
是供已连接互联网的设备进行通信的通信规则

OSI模型只是一个基本概念,而TCP/IP协议是基于这个概念的具体实现

TCP和UDP协议

TCP:传输控制协议,面向连接,更安全,效率较低,一对一
UDP:用户数据报协议,无连接,不保证可靠性,效率较高,随意组合

TCP

是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接
并且在消息传送过程中是有顺序的,并且是不会丢包(丢弃消息)的
如果某一条消息在传送过程中失败了,会重新发送消息,直到成功

三次握手 四次挥手

三次握手建立连接
第一次握手(C->S)
TCP连接请求
第二次握手(S->C)
TCP授予连接
第三次握手(C->S)
TCP确认连接

四次挥手断开连接
第一次挥手(C->S)
客户端告诉服务器数据已经发完,如果服务器还有消息就请快发完
第二次挥手(S->C)
服务器告诉客户端继续等待服务器的消息
第三次挥手(S->C)
服务器告诉客户端消息发送完成,可以正式断开连接
第四次挥手(C- ->S)
客户端告诉服务器等一会如果没有收到服务器回复就断开 了

提供可靠的服务,通过TCP连接传送的数据,做到无差错、不丢失、不重复、且按顺序到达

UDP

是一种无需建立连接就可以发送封装的IP数据包的方法,提供了面向事务的简单不可靠信息传送服务

具有资源消耗小,处理速度快的特点

UDP协议不像TCP协议需要建立连接有三次握手和四次挥手,当使用UDP协议发送信息时会直接把信息数据扔到网络上,所以也就造成了UDP的不可靠性。信息在这个传递过程中是有可能丢失的虽然UDP是一个不靠谱的协议,但是由于它不需要建立连接。也不会像TCP协议那样携带更多的信息,所以它具有更好的传输效率
 

网络游戏通信方案

Socket\HTTP\FTP

Socket:网络嵌套字

HTTP:超文本传输协议,主要完成短链接网络游戏需求

FTP:主要用来完成资源的下载和上传

byte [] ipAddress = new byte[]{118,102,111,11};
IPAddress ip1 =new IPAddress(ipAddress);
//用byte进行初始化//使用字符串进行初始化
IPAdress ip =IPAddress.Parse("118.102.111.11");//ipi27.0.0.1代表本机地址//命名空间System.NetIPEndPoint ipPoint =new IPEndPoint(0x79666F0B,8080);
IPEndPoint ipPoint2 =new IPEndPoint(IPAddress.Parse("118.102.111.11"),8080);

域名解析

也叫域名指向,服务器设置,域名配置

域名系统是互联网上的一种服务,管理名字与IP的对应关系

//IPHostEntry类
//域名解析后的返回值,可以获取该对象的IP地址主机名等信息//DNS类
print(Dns.GetHostName());
//获取主机名字//获取指定域名的ip地址
//可能会阻塞主线程
IPHostEntry entry = Dns.GetHostEntry("www.baidu.com");for(int i=0;i<entry.AddressList.Length;i++){print(entry.AddressList[i]);
}

Socket 套接字

c#用于提供网络通信的一个类

类名:Socket          命名空间:System.Net.Socket

Socket套接字时支持TCP/IP网络通信的基本操作单位

一个套接字包括:本机地址IP和端口/对方主机的IP地址和端口/双方通信的协议信息

一个Socket对象表示一个本地或者远程嵌套字信息,可被视为一个数据通道,链接服务器和客户端,可以接受数据的发送和接收

适合长连接的网络游戏

AddressFamily 网络寻址 枚举类型,决定寻址方案
        InterNetwork IPv4寻址
        InterNetwork6 IPv6寻址

SocketType 嵌套字枚举类型 决定使用的套接字类型
        Dgram 支持数据报,最大长度固定,无连接,不可靠的消息(主要用于UDP通信)
        Stream 支持可靠、双向、基于连接的字节流(主要用于TCP通信)

ProtocolType 协议类型枚举,决定套接字使用的通信协议

        TCP

        UDP

流套接字

主要实现TCP通信

数据报套接字

主要实现UDP通信

    //TCP流套接字Socket socketTcp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//UDPSocket socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

实现服务端基本逻辑

 //创建套接字Socket socketTcp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//用bind方法将套接字与本地地址绑定//端口号要大于1024,且不能被占用IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080);try{socketTcp.Bind(ipPoint);}catch (Exception e){return;}//用LISTEN监听socketTcp.Listen(1024);//accept等待客户端连入//建立连接,返回套接字Socket socketClient =socketTcp.Accept();//收发数据socketClient.Send(Encoding.UTF8.GetBytes("HFUT"));byte[] result=new byte[1024];int receiveNum=socketClient.Receive(result);//返回值为接收到的数量socketClient.Shutdown(SocketShutdown.Both);socketClient.Close();

实现客户端基本逻辑

//创建套接字Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//与服务端相连IPEndPoint ipPoint =new IPEndPoint(IPAddress.Parse("127.0.0.0"), 8080);//上述应填写服务端的IP地址try{socket.Connect(ipPoint);}catch(SocketException e) {if(e.ErrorCode ==10061){}else{}}//收发数据byte[] data = new byte[1024];int num = socket.Receive(data);//发送数据socket.Send(Encoding.UTF8.GetBytes("HFUTER"));socket.Shutdown(SocketShutdown.Both);socket.Close();

区分消息类型

发送自定义类的二进制信息(需要继承BaseData类)

区分不同消息:给发送的消息添加标识,比如添加消息ID

例如选择int做消息ID,那么热前四个字节为消息ID,后面为数据类的内容

实现:

        1.创建一个消息基类,基类继承BaseData,基类添加获取消息的ID的方法或者属性

        2.让想要被发送的消息继承该类,实现序列化反序列化的方法

        3.写客户端和服务端收发处理消息的逻辑

分包与黏包

网络通信中由于各种因素造成的消息与消息之间出现的两种状态

分包:一个消息分成了多个消息进行发送

黏包:一个消息和另一个消息黏在一起

两者可能同时发生

解决办法:

可以通过消息的长度来判断是否出现分包或者黏包

为消息添加长度,消息长度记录消息的长度

心跳信息

在长连接中,客户端和服务端之间定期发送的一种特殊数据包,通知对方自己还在线,以保证长连接的有效性

其发送时间间隔是固定的,且持续,因此称之为心跳消息

心跳消息可以避免非正常关闭客户端时,服务器无法正常收到关闭连接消息,同时避免客户端长期不发消息,防火墙或者路由器会断开连接

当客户端主动断开时,服务端无法得知客户端已经主动断开

在客户端中可以使用Disconect方法,看是否因为之前直接Close()从而没有调用Disconect造成服务端无法及时获取状态(仍然无法准确地让服务端得知客户端已经断开连接)

可以考虑自定义退出消息

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class QuitMsg : BaseMsg
{//继承自消息基类//主动发送一条断开连接的消息给服务端//重写函数public override int GetBytesNum(){return 8;}public override int Reading(byte[] bytes, int beginIndex = 0){return 0;}public override byte[] Writing(){int index = 0;byte[] bytes = new byte[GetBytesNum()];WriteInt(bytes, GetID(), ref index);WriteInt(bytes, 0, ref index);return bytes;}public override int GetID(){return 1003;}
}

实现心跳消息

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class HeartMsg : BaseMsg
{//继承消息基类public override int GetBytesNum(){return 8;}public override int Reading(byte[] bytes, int beginIndex = 0){//不需要反序列化任何变量return 0;}public override byte[] Writing(){int index = 0;byte[] bytes = new byte[GetBytesNum()];WriteInt(bytes, GetID(), ref index);WriteInt(bytes, 0, ref index);return bytes;}public override int GetID(){return 999;}
}

客户端:定时发送消息

服务端:收心跳消息 记录收到消息的时间

异步通信

方法中的逻辑还没执行完,便继续执行后面的内容

UNITY中的协同程序中的某系异步方法,有的使用的是多线程有的使用的是迭代器分步执行

//线程回调
public void CountDownAsync(int second, UnityAction callBack){Thread t = new Thread(() =>{while (true){print(second);Thread.Sleep(1000);--second;if (second == 0)break;}
//?的目的是,如果是空的,则不会执行callBack?.Invoke();});t.Start();print("开始倒计时");}//让函数分布执行public async void CountDownAsync(int second){print("倒计时开始");//await->Task通过线程池开启一个线程
//本质上将函数分布执行await Task.Run(() =>{while (true){print(second);Thread.Sleep(1000);--second;if (second == 0)break;}});print("倒计时结束");}

UCP通信

udp不会对数据包进行合并发送,不会出现黏包问题

UDP是不可靠连接,消息传递过程中可能出现无序、丢包等情况

为了避免分包,建议控制消息的大小在MTU(最大传输单元)范围内

MTU:

最大传输单元,用来通知对方所能接受数据服务单元的最大尺寸

局域网:1472字节以内     互联网:548字节以内

如果想要发送的消息过大,可以进行手动分包,但是手动分包的前提是解决UDP的无序和丢包的问题

UDP流程更简单,效率高,但是不可靠

FTP

是支持因特网文件传输的各种规则的集合,使得文件可以被从一台主机拷贝到另一台主机上。此外,FTP还提供登录、文件查询以及其他绘画控制等功能

FTP本质上是TCP通信通过FTP,双发至少需要简历两个TCP连接,一个称为控制连接,一个成为数据连接

FTP的数据连接和控制连接方向一般是相反的

两种传输方式:1.ASCII传输    2.二进制传输

FTP关键类

1.NetworkCredential 通信凭证类 

命名空间:System.Net

用于Ftp文件传输,设置账号密码

NetworkCredrntial n =new NetworkCredrntial("HFUTER","hfuter");


2.FtpWebRequest Ftp文件传输客户端操作类

命名空间:System.Net

用于上传,下载,删除服务器上的文件
3.FtpWebResponse类

FtpWebRequest req = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/Test.txt")) as FtpWebRequest;//创建req.Abort();//停止Stream s=  req.GetRequestStream();//获取流对象FtpWebResponse res= req.GetResponse() as FtpWebResponse;//返回FTP服务器响应

HTTP

HTTP超文本传输协议就是一个在网络中上传下载文件的一套规则

其本质也是TCP通信,因此不会丢包、不会乱序

1.以TCP方式工作:

HTTP/1.1支持持久连接(目前使用版本)

2.HTTP是无状态的:

HTTP不会记录客户端请求过的状态

3.元信息作为标头

主要数据前添加一段额外信息

请求类型和相应状态码

HTTP/1.1:GET\POST\HEAD\PUT\......

响应状态码:1xx\2xx\3xx\4xx\5xx

GET:请求获取特定的资源

POST:请求提交数据进行处理

HTTP常用状态码:

200 OK;404 NOT FOUND;405 不支持请求的方法;501 服务器不能识别请求挥着没有实现指定的请求

关键类

HttpWebRequest类:

命名空间:System.Net
HttpWebRequest是主要用于发送客户端请求的类
主要用于:发送HTTP客户端请求给服务器,可以进行消息通信、上传、下载等等操作
 

//创建新的WebRequest,用于进行HTTP相关操作HttpWebRequest req = HttpWebRequest.Create(new Uri("http://192.168.50.109:8000/Http_Server/")) as HttpWebRequest;//终止传输 req.Abort();//获取用于上传的流Stream s = req.GetRequestStream();//返回HTTP服务器响应HttpWebResponse res = req.GetResponse() as HttpWebResponse;//异步获取用于上传的流req.BeginGetRequestStream()异步获取返回的HTTP服务器响应//req.BeginGetResponse()

HttpWebResponse类:


命名空间:System.Net
主要用于获取服务器反馈信息的类,可以通过HttpWebRequest对象中的GetResponse()方法获取。当使用完毕时,要使用Close释放

POST

上传文件到HTTP资源服务器需要遵守的规则:

1:ContentType = "multipart/form-data; boundary=边界字符串";

2:上传的数据必须按照格式写入流中

3:保证服务器允许上传

4:写入流前需要先设置ContentLength内容长度

WWW类

WWW是Unity提供给程序员简单的访问网页的类,可以通过该类下载和上传一些数据,在使用http协议时,默认的请求类型是Get,如果想要Post上传,需要配合WWWFrom类使用(该类在较新Unity版本中会提示过时,但是仍可以使用,新版本将其功能整合进了UnityWebRequest类)

主要支持的协议:

1.http://和https:// 超文本传输协议
2.ftp:// 文件传输协议(但仅限于匿名下载)
3.file:// 本地文件传输协议,可以使用该协议异步加载本地文件(PC、IOS、Android都支持)

//创建
WWW www = new WWW("");//从下载数据返回一个音效切片AudioClip对象
www.GetAudioClip();//用下载数据中的图像来替换现有的一个Texture2D对象
Texture2D tex = new Texture2D(100, 100);//从缓存加载AB包对象,如果该包不在缓存则自动下载存储到缓存中,以便以后直接从本地缓存中加载
WWW.LoadFromCacheOrDownload("", 1);

UnityWebRequest

是一个Unity提供的一个模块化的系统类,用于构成HTTP请求和处理HTTP响应,主要目标是让Unity游戏和Web服务端进行交互,将之前WWW的相关功能都集成在了其中(新版本中都建议使用UnityWebRequest类来代替WWW类)

注意:
1.UnityWebRequest和WWW一样,需要配合协同程序使用
2.UnityWebRequest和WWW一样,支持http、ftp、file协议下载或加载资源
3.UnityWebRequest能够上传文件到HTTP资源服务器

UnityWebRequest类的常用操作:

        //1.获取文本或2进制StartCoroutine(LoadText());//2.获取纹理StartCoroutine(LoadTexture());//3.获取AB包StartCoroutine(LoadAB());IEnumerator LoadText(){UnityWebRequest req = UnityWebRequest.Get("http://192.168.50.109:8000/Http_Server/test.txt");//就会等待 服务器端响应后 断开连接后 再继续执行后面的内容yield return req.SendWebRequest();//如果处理成功 结果就是成功枚举if(req.result == UnityWebRequest.Result.Success){//独立的处理对象print(req.downloadHandler.text);byte[] bytes = req.downloadHandler.data;print("字节数组长度" + bytes.Length);}else{print("获取失败:" + req.result + req.error + req.responseCode);}}IEnumerator LoadTexture(){//UnityWebRequest req = UnityWebRequestTexture.GetTexture("http://192.168.50.109:8000/Http_Server/HFUTER.jpg");//UnityWebRequest req = UnityWebRequestTexture.GetTexture("ftp://127.0.0.1/HFUTER.jpg");UnityWebRequest req = UnityWebRequestTexture.GetTexture("file://" + Application.streamingAssetsPath + "/test.png");yield return req.SendWebRequest();if (req.result == UnityWebRequest.Result.Success){//(req.downloadHandler as DownloadHandlerTexture).texture//DownloadHandlerTexture.GetContent(req)//image.texture = (req.downloadHandler as DownloadHandlerTexture).texture;image.texture = DownloadHandlerTexture.GetContent(req);}elseprint("获取失败" + req.error + req.result + req.responseCode);}IEnumerator LoadAB(){UnityWebRequest req = UnityWebRequestAssetBundle.GetAssetBundle("http://192.168.50.109:8000/Http_Server/lua");req.SendWebRequest();while (!req.isDone){print(req.downloadProgress);print(req.downloadedBytes);
//每帧执行yield return null;}//yield return req.SendWebRequest();print(req.downloadProgress);print(req.downloadedBytes);if (req.result == UnityWebRequest.Result.Success){//AssetBundle ab = (req.downloadHandler as DownloadHandlerAssetBundle).assetBundle;AssetBundle ab = DownloadHandlerAssetBundle.GetContent(req);print(ab.name);}elseprint("获取失败" + req.error + req.result + req.responseCode);}

这篇关于[Unity3d] 网络开发基础【个人复习笔记/有不足之处欢迎斧正/侵删】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/772232

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识