unity动态加载obj文件

article/2025/10/25 4:05:36

unity2018.4.2f1

vs2017

最近项目需求,需要实现动态读物外部obj模型,并加载到场景中,研究了好几天,终于实现了,在此做个记录。

1、首先随便找个.obj模型,带贴图,我的资源截图如下:

  .mtl文件是负责记录模型与贴图的对应关系

obj问价与mtl文件均可以用记事本打开,查看内部数据

obj文件截图:

mtllib Tifa.mtl   记录当前obj文件对应的mtl文件的名称(一个mtl文件可以包含多个材质)

v:模型顶点数据

vt:模型顶点纹理坐标数据

vn:模型顶点法线数据

usemtl diss_00.png 表示当前模型分组使用的材质,每一个模型分组以usemtl 开始(一个模型存在有多个子物体的情况)

比如我这个:

mtl文件截图:

newmtl diss_00.png:表示当前的材质名称

illum:照明度(0-10)

kd:当前材质的散射光

ka:当前材质的环境光

ks:当前材质的镜面光

ke:当前材质的散射光

Ns:材质的光亮度

map_Kd:当前材质对应的贴图名称

2、根据模型文本文件分析,编写模型数据结构,直接上代码

ObjPart:obj文件数据结构

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ObjPart
{/// <summary>/// 材质名称/// </summary>public string strMatName;/// <summary>/// UV坐标数组/// </summary>public List<Vector2> listUV; //vt/// <summary>/// 法线数组/// </summary>public List<Vector3> listNormal;//vn/// <summary>/// 切线数组/// </summary>public List<Vector4> listTangent;/// <summary>/// 顶点数组/// </summary>public List<Vector3> listVertex; //v/// <summary>/// 面数组 面索引/// </summary>public List<int> listTriangle;public ObjPart(){strMatName = "";listUV = new List<Vector2>();listNormal = new List<Vector3>();listVertex = new List<Vector3>();listTriangle = new List<int>();listTangent = new List<Vector4>();}
}

ObjMatItem:mtl文件数据结构

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//mtl数据结构(记录的是材质对应的贴图)
public class ObjMatItem 
{/// <summary>/// 材质名称/// </summary>public string strMatName;public int illum;public Vector3 Kd;public Vector3 Ka;public Vector3 Tf;public Vector2 widthHeight;public string map_Kd;public float Ni;public ObjMatItem(){strMatName = "";illum = -1;Kd = new Vector3(0.0f, 0.0f, 0.0f);Ka = new Vector3(0.0f, 0.0f, 0.0f);Tf = new Vector3(0.0f, 0.0f, 0.0f);map_Kd = "";Ni = 1.0f;widthHeight.x = 0.0f;widthHeight.y = 0.0f;}
}

ObjModel:模型数据结构

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 完整模型=网格+材质
/// </summary>
public class ObjModel 
{public List<ObjPart> objParts;   //网格public List<ObjMatItem> ObjMats; //材质
}

3、从文本文件中加载obj数据以及mtl数据

ObjMesh:负责从.obj文件中加载数据

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;/// <summary>
/// 负责从.obj文件中加载数据
/// </summary>
public class ObjMesh 
{/// <summary>/// UV坐标列表/// </summary>private List<Vector3> uvArrayList;/// <summary>/// 法线列表/// </summary>private List<Vector3> normalArrayList;/// <summary>/// 顶点列表/// </summary>private List<Vector3> vertexArrayList;public List<ObjPart> listObjParts;public List<ObjMatItem> listObjMats;public string _strMatPath { get; set; }public string _strObjPath { get; set; }public string _strObjName { get; set; }/// <summary>/// 构造函数    /// </summary>public ObjMesh(){//初始化列表uvArrayList = new List<Vector3>();normalArrayList = new List<Vector3>();vertexArrayList = new List<Vector3>();listObjParts = new List<ObjPart>();listObjMats = new List<ObjMatItem>();_strMatPath = _strObjName = "";}/// <summary>/// 从一个文本化后的.obj文件中加载模型/// </summary>public ObjMesh LoadFromObj(string strObjPath){_strObjPath = strObjPath;_strObjName = strObjPath;_strObjName = _strObjName.Replace("/", "");//读取内容if (!File.Exists(strObjPath)) return null;StreamReader reader = new StreamReader(strObjPath, System.Text.Encoding.Default);string objText = reader.ReadToEnd();reader.Close();if (objText.Length <= 0)return null;//v这一行在3dsMax中导出的.obj文件//  前面是两个空格后面是一个空格objText = objText.Replace("  ", " ");//将文本化后的obj文件内容按行分割string[] allLines = objText.Split('\n');foreach (string line in allLines){//将每一行按空格分割char[] charsToTrim = { ' ' };string[] chars = line.TrimEnd('\r').TrimStart(' ').Split(charsToTrim, StringSplitOptions.RemoveEmptyEntries);if (chars.Length <= 0){continue;}//根据第一个字符来判断数据的类型switch (chars[0]){case "mtllib":_strMatPath = _strObjPath.Substring(0, _strObjPath.LastIndexOf('/') + 1) + chars[1];break;case "v"://处理顶点this.vertexArrayList.Add(new Vector3(-(ConvertToFloat(chars[1])),ConvertToFloat(chars[2]),ConvertToFloat(chars[3])));break;case "vn"://处理法线this.normalArrayList.Add(new Vector3(-ConvertToFloat(chars[1]),ConvertToFloat(chars[2]),ConvertToFloat(chars[3])));break;case "vt"://处理UVthis.uvArrayList.Add(new Vector3(ConvertToFloat(chars[1]),ConvertToFloat(chars[2])));break;case "usemtl":ObjPart objPart = new ObjPart();objPart.strMatName = chars[1];//材质名称listObjParts.Add(objPart);break;case "f"://处理面GetTriangleList(chars);break;}}//获取mtl文件路径// string mtlFilePath = strObjPath.Replace(".obj", ".mtl");if (_strMatPath != ""){LoadMat(_strMatPath);}return this;}private void LoadMat(string strmtlPath){//从mtl文件中加载材质listObjMats = ObjMaterial.Instance.LoadFormMtl(strmtlPath);}/// <summary>/// 获取面列表./// </summary>/// <param name="chars">Chars.</param>/// private List<Vector3> indexVectorList = new List<Vector3>();private Vector3 indexVector = new Vector3(0, 0);private void GetTriangleList(string[] chars){indexVectorList.Clear();for (int i = 1; i < chars.Length; ++i){//将每一行按照空格分割后从第一个元素开始//按照/继续分割可依次获得顶点索引、法线索引和UV索引string[] indexs = chars[i].Split('/');Vector3 vertex = (Vector3)vertexArrayList[ConvertToInt(indexs[0]) - 1];listObjParts[listObjParts.Count - 1].listVertex.Add(vertex);indexVector = new Vector3(0, 0);//UV索引if (indexs.Length > 1){if (indexs[1] != "")indexVector.y = ConvertToInt(indexs[1]);}//法线索引if (indexs.Length > 2){if (indexs[2] != "")indexVector.z = ConvertToInt(indexs[2]);}//给UV数组赋值if (uvArrayList.Count > 0 && indexVector.y > 0.01){Vector3 tVec = (Vector3)uvArrayList[(int)indexVector.y - 1];listObjParts[listObjParts.Count - 1].listUV.Add(new Vector2(tVec.x, tVec.y));}//给法线数组赋值if (normalArrayList.Count > 0 && indexVector.z > 0.01){Vector3 nVec = (Vector3)normalArrayList[(int)indexVector.z - 1];listObjParts[listObjParts.Count - 1].listNormal.Add(nVec);}//将索引向量加入列表中indexVectorList.Add(indexVector);}//面索引int nCount = listObjParts[listObjParts.Count - 1].listVertex.Count - indexVectorList.Count; //nCount==0 3 6 9 indexVectorList.Count=3 三角形面//Debug.Log(indexVectorList.Count);for (int j = 1; j < indexVectorList.Count - 1; ++j){//按照0,1,2这样的方式来组成面          listObjParts[listObjParts.Count - 1].listTriangle.Add(nCount);listObjParts[listObjParts.Count - 1].listTriangle.Add(nCount + j);listObjParts[listObjParts.Count - 1].listTriangle.Add(nCount + j + 1);}}/// <summary>/// 将一个字符串转换为浮点类型/// </summary>/// <param name="s">待转换的字符串</param>/// <returns></returns>private float ConvertToFloat(string s){//return (float)System.Convert.ToDouble(s,CultureInfo.InvariantCulture);float fValue = 0.0f;try{fValue = (float)Convert.ToDouble(s);}catch (Exception ex){Debug.LogError("数据[" + s + "]转换失败! " + ex.Message);}return fValue;}/// <summary>/// 将一个字符串转化为整型 /// </summary>/// <returns>待转换的字符串</returns>/// <param name="s"></param>private int ConvertToInt(string s){//return System.Convert.ToInt32(s, CultureInfo.InvariantCulture);int nValue = 0;try{nValue = Convert.ToInt32(s);}catch (Exception ex){Debug.LogError("数据[" + s + "]转换失败! " + ex.Message);}return nValue;}
}

ObjMaterial:负责从.mtl中加载数据

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;/// <summary>
/// 负责从.mtl中加载数据
/// </summary>
public class ObjMaterial
{/// <summary>/// 当前实例/// </summary>private static ObjMaterial instance=new ObjMaterial();public static ObjMaterial Instance{get{if (instance == null)instance = new ObjMaterial();//GameObject.FindObjectOfType<ObjMaterial>(); return instance;}}/// <summary>/// 从一个文本化后的mtl文件加载一组材质/// </summary>/// <param name="mtlText">文本化的mtl文件</param>/// <param name="texturePath">贴图文件夹路径</param>public List<ObjMatItem> LoadFormMtl(string strMtlText){List<ObjMatItem> listObjMats = new List<ObjMatItem>();DirectoryInfo mtlParent=Directory.GetParent(Settings.ObjPath);if (!File.Exists(mtlParent + "\\" + strMtlText)) return null;Stream mtlStream = new FileStream(mtlParent+"\\"+ strMtlText,FileMode.Open);//mtl文件与obj文件处于同一级目录下StreamReader reader = new StreamReader(mtlStream);string mtlText = reader.ReadToEnd();reader.Close();if (mtlText == "")return listObjMats;//将文本化后的内容按行分割string[] allLines = mtlText.Split('\n');foreach (string line in allLines){//按照空格分割每一行的内容string[] chars = line.TrimEnd('\r').TrimStart(' ').Split(' ');switch (chars[0]){case "newmtl"://处理材质名ObjMatItem matItem = new ObjMatItem();matItem.strMatName = chars[1];listObjMats.Add(matItem);//根据贴图创建材质球break;case "Ka":listObjMats[listObjMats.Count - 1].Ka = new Vector3(ConvertToFloat(chars[1]),ConvertToFloat(chars[2]),ConvertToFloat(chars[3]));break;case "Kd"://处理漫反射listObjMats[listObjMats.Count - 1].Kd = new Vector3(ConvertToFloat(chars[1]),ConvertToFloat(chars[2]),ConvertToFloat(chars[3]));break;case "Ks"://暂时仅考虑漫反射break;case "Ke"://Todobreak;case "Tf"://处理漫反射listObjMats[listObjMats.Count - 1].Tf = new Vector3(ConvertToFloat(chars[1]),ConvertToFloat(chars[2]),ConvertToFloat(chars[3]));break;case "Ni":listObjMats[listObjMats.Count - 1].Ni = ConvertToFloat(chars[1]);break;case "e"://Todobreak;case "illum":listObjMats[listObjMats.Count - 1].illum = Convert.ToInt32(chars[1]);break;case "map_Ka"://暂时仅考虑漫反射break;case "map_Kd"://处理漫反射贴图string textureName = chars[1].Substring(chars[1].LastIndexOf("\\") + 1, chars[1].Length - chars[1].LastIndexOf("\\") - 1);listObjMats[listObjMats.Count - 1].map_Kd = textureName;break;case "map_Ks"://暂时仅考虑漫反射break;}}GameObject.Find("Canvas").GetComponent<LoadModel>().CreatMaterial(listObjMats);return listObjMats;}/// <summary>/// 将一个字符串转换为浮点类型/// </summary>/// <param name="s">待转换的字符串</param>/// <returns></returns>private float ConvertToFloat(string s){return System.Convert.ToSingle(s);}}

Settings:记录数据

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Settings
{public static string ObjPath=null;           //模型路径public static Dictionary<string, Material> ModelMaterialList = new Dictionary<string, Material>();//材质球存储 key:材质名称 value:材质球
}

4、开始使用获得的文件数据,在场景中加载模型

LoadModel:创建模型(该脚本挂载到canvas上,由按钮触发LoadModelEvent函数 开始创建模型)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System;
using System.IO;public class LoadModel : MonoBehaviour
{private List<ObjMesh> listObjModel = new List<ObjMesh>();private List<ObjMatItem> listObjMats = new List<ObjMatItem>();private List<ObjPart> listObjParts = new List<ObjPart>();private GameObject goParent;public GameObject _gameObj;    //模型父节点private bool isDone = false;    //true:材质球全部创建完成后 给模型贴材质//按钮事件处理public void LoadModelEvent(){string strObjPath = "C:\\Users\\123\\Desktop\\obj__001\\123\\飞马\\飞马 .obj";Settings.ObjPath = strObjPath;ObjMesh objInstace = new ObjMesh();objInstace = objInstace.LoadFromObj(strObjPath);if (objInstace == null) return;listObjModel.Add(objInstace);listObjParts = objInstace.listObjParts;//模型Debug.Log("Parts:" + listObjParts.Count);listObjMats = objInstace.listObjMats;  //材质if(listObjMats!=null)Debug.Log("Mats:" + listObjMats.Count);string strGameName = strObjPath;strGameName = strGameName.Replace("/", "");string[] names = strGameName.Split('\\');strGameName = names[names.Length - 1];goParent = new GameObject(strGameName); //模型资源名称StartCoroutine(WaitLoadMaterialTexture());}IEnumerator WaitLoadMaterialTexture(){while (!isDone&& listObjMats!=null) //等待材质创建完成{yield return null;}//计算网格int i = 0;foreach (ObjPart part in listObjParts){++i;Mesh mesh = new Mesh();mesh.vertices = part.listVertex.ToArray();//顶点//mesh.triangles = part.listTriangle.ToArray();mesh.triangles= ResetTriangles(part.listTriangle.ToArray());//修改三角形面 翻转三角形面if (part.listUV.Count > 0){mesh.uv = part.listUV.ToArray();}if (part.listNormal.Count > 0){mesh.normals = part.listNormal.ToArray();}mesh.tangents = part.listTangent.ToArray(); //切线mesh.RecalculateBounds();// mesh.RecalculateNormals(); //法线//生成物体GameObject go = new GameObject(part.strMatName + i.ToString());// ==go.AddComponent<ObjDestroy>();MeshFilter meshFilter = go.AddComponent<MeshFilter>();meshFilter.mesh = mesh;//parts里面存储的有材质名称 根据材质名称生成材质球MeshRenderer render = go.AddComponent<MeshRenderer>();RenderAddMaterials(go, part);go.transform.SetParent(goParent.transform);}goParent.transform.SetParent(_gameObj.transform);}//翻转法线private Vector3[] FlipNormals(Vector3[] normals){Vector3[] res=new Vector3[normals.Length];for (int i = 0; i < normals.Length; i++){normals[i] = -normals[i];}return normals;}//翻转三角形面片private int[] ResetTriangles(int[] triangles){for (int i = 0; i < triangles.Length; i+=3){int t = triangles[i];triangles[i] = triangles[i + 2];triangles[i + 2] = t;}return triangles;}private void RenderAddMaterials(GameObject go, ObjPart part){//给模型添加材质球if (Settings.ModelMaterialList.ContainsKey(part.strMatName)){go.GetComponent<MeshRenderer>().material = Settings.ModelMaterialList[part.strMatName];}}//创建所有需要的材质球(mtl文件与obj文件读取完成后,调用)public void CreatMaterial(List<ObjMatItem> matList){int nowIndex = 0;foreach (ObjMatItem item in matList){++nowIndex;string textureName = item.map_Kd;//贴图名称string texturePath = Directory.GetParent(Settings.ObjPath).FullName + "\\" + textureName;StartCoroutine(LoadTexture(item, nowIndex, matList.Count));}}/// <summary>/// 加载贴图   /// </summary>IEnumerator LoadTexture(ObjMatItem item, int nowIndex, int maxIndex){string texturePath = Directory.GetParent(Settings.ObjPath).FullName + "\\" + item.map_Kd;  //图片路径string matName = item.strMatName;//材质名称if (!File.Exists(texturePath)) { yield break; } //终止协成UnityWebRequest request = new UnityWebRequest(texturePath);DownloadHandlerTexture tex = new DownloadHandlerTexture(true);request.downloadHandler = tex;yield return request.SendWebRequest();if (!request.isNetworkError){Texture2D texture = tex.texture;       //下载的东西不用时要清空 否则内存占用会越来越多TODOMaterial material = new Material(Shader.Find("Standard"));material.mainTexture = texture;Settings.ModelMaterialList.Add(matName, material);if (nowIndex == maxIndex){isDone = true;}}else{Debug.LogError("load texture failed!");}}
}

5、实现过程中遇到的困难

首先脚本数据结构以及文件读取都是从网上找的,然后结合自己的实际需求稍作修改。

比如mtl文件、obj文件以及贴图都在同一路径,所以读取路径拼接方式全部都改了;

模型材质加载是自己加上去的,根据mtl文件创建对应的材质球,存储起来,模型的子节点根据材质名称选择贴哪个材质;

其中最大的问题是模型网格面反了,导致贴上贴图后模型看起来是透明的,问了老大,说可能是法线反了,改了没效果,就百度下mesh的知识,看了下网格加载部分的代码,注意到加载顶点以及法线时vector3的第一个数据取反了,如下图所示:

所以面反了,根据这个将mesh中的triangles三角形面翻转,最后完美实现加载。

有想法的可以留言,时间长了我估计有可能记不清了,就不能都回复了

 


http://chatgpt.dhexx.cn/article/KWxSETjD.shtml

相关文章

obj文件(3): 如何用matlab 打开obj文件

obj文件:如何用 matlab 打开 obj 文件 第一步&#xff1a;检查obj文本格式第二步&#xff1a;用 Blender 软件重新导出obj文件第三步&#xff1a;用excel 打开这个obj 文件第四步&#xff1a;复制excel中的数据&#xff0c;传给matlab第五步&#xff1a; 用matlab 打开3D模型 第…

三维模型obj文件解析

目录 obj文件简介文件结构顶点数据(Vertex data)&#xff1a;自由形态曲线(Free-form curve)/表面属性(surface attributes):元素(Elements):自由形态曲线(Free-form curve)/表面主体陈述(surface body statements):自由形态表面之间的连接(Connectivity between free-form sur…

linux类动态库,Linux动态库(一)

起因 博主在以Linux下做开发。在软件需求中&#xff0c;需要动态库带来的灵活性。 比如说博主主导的智能主机的开发。它需要支持很多种类的设备控制&#xff0c;如普通的开关灯、RGB灯、窗帘、百叶窗等等。我们将这些设备抽象成Device类&#xff0c;具体的设备就从这个类上派生…

OpenFlow Switch

The picture of OpenFlow Switch openflow 架构分为2层&#xff0c;一个是控制器层&#xff0c;一个是switch 层。中间是由openflow protocal进行连接的&#xff0c;负责传输指令与数据。switch分为3大块&#xff0c;第一是openflow channe&#xff0c;他是负责向控制器传输数据…

【博客450】OpenFlow学习

OpenFlow OpenFlow协议规范定义了OpenFlow交换机、流表、OpenFlow通道以及OpenFlow交换协议。 OpenFlow是第一个开放的南向接口协议&#xff0c;也是目前最流行的南向协议。它提出了控制与转发分离的架构&#xff0c;规定了SDN转发设备的基本组件和功能要求&#xff0c;以及与控…

OpenFlow交换机【ACM SIGCOMM顶会论文笔记】

目录 写在前面的话OpenFlow交换机基本思想与工作原理专用OpenFlow交换机&#xff08;Dedicated OpenFlow switches&#xff09; 启用OpenFlow的交换机&#xff08;OpenFlow-enabled switches&#xff09;其他功能&#xff08;Additional features&#xff09;控制器&#xff08…

关于ns-3中安装openflow的问题,解决openflow not found

官网 官网里面并没有明确的描述&#xff0c;这里结合自己的安装过程讲解一下 首先下载源码&#xff0c;记住这一步最好在ns-3目录下&#xff0c;就是运行waf命名的目录 $ hg clone http://code.nsnam.org/jpelkey3/openflow $ cd openflow进行编译&#xff0c;会提示缺少文件…

OpenFlow基础入门知识

本文进行讨论的是OpenFlow 1.0和OpenFlow 1.3的基本知识 Overview&#xff1a; Openflow 1.0&#xff1a; 安全通道单张流表ipv4 Openflow 1.3&#xff1a; 安全通道多级流表&#xff08;流水线pipeline&#xff09;组表测量表ipv6..... 流&#xff08;flow&#xff09; …

Openflow流表学习

Openflow流表学习 OpenFlow是一种新型的网络协议&#xff0c;它是控制器和交换机之间的标准协议。自2009年底发布1.0版本后&#xff0c;OpenFlow协议又经历了1.1、1.2、1.3及1.4版本的演进过程&#xff0c;目前使用和支持最多的是1.0和1.3版本。 OpenFlow1.3在1.0版的基础上进…

SDN与OPENFLOW 简介

本文对Openflow的发展、规范、应用和SDN的提出及相关应用做出较为客观全面的介绍。笔者希望通过本文对OpenFlow/SDN做一个初步介绍&#xff0c;以期帮助大家能够进一步深入了解和学习OpenFlow/SDN。 序言&#xff1a;从网络虚拟化说起 云计算的发展&#xff0c;是以虚拟化技术…

OpenFlow协议分析

实验环境&#xff1a;CentOS OpenDayLight-Carbon mininet WireShark 本实验通过wireshark抓包分析openflow1.3协议的各种报文与字段。 抓包 首先安装好实验所需的软件&#xff0c;这里不多赘述&#xff0c;需要的可以点击查看&#xff1a;mininet多方法安装&#xff0c;控制…

openflow简介

openflow交换机包含一些流表&#xff0c;流表负责具体包查找和转发 控制器通过of协议对流表查询和管理 一、流表 流表组成&#xff1a; 包头域、活动计数器、0个或多个执行行动 包头域&#xff1a; 计数器&#xff1a; 可以针对每张表、每个流、每个端口、每个队列来维护。…

SDN-OpenFlow1.0协议分析

目录 OpenFlow1.0代码 OpenFlow交换机流表 包头域 计数器 行动 流表匹配 OpenFlow消息 OpenFlow消息格式 对称消息 建立OpenFlow连接&#xff08;OFPT_HELLO消息&#xff09; 报告错误&#xff08;OFPT_ERROR消息&#xff09; 获取交换机特性信息&#xff08;Featu…

OpenFlow概述

OpenFlow简介 通俗的讲&#xff0c;OpenFlow是使用类似于API进程配置网络交换机的协议。OpenFlow的思路很简单&#xff0c;网络设备维护一个FlowTable并且只按照FlowTable进行转发&#xff0c;FlowTable本身的生成、维护、下发完全由外置的Controller来实现&#xff0c;注意这里…

OpenFlow了解

openflow的核心思想是将所有的协议都抽象出来&#xff0c;抽象成公共的flow概念。协议抽象&#xff1a;数据&#xff0c;函数&#xff08;对数据的处理方式&#xff09;&#xff0c;逻辑&#xff08;数据与处理的对应关系&#xff0c;函数之间的交互行为与时序&#xff09; pu…

OpenFlow交换机概述

1 交换机组成 OpenFlow交换机包括一个或多个流表和一个组表&#xff0c;执行分组查找和转发&#xff0c;和到一个外部控制器OpenFlow的信道。 控制器使用OpenFlow的协议&#xff0c;可添加、更新和删除流表中表项&#xff0c;既主动或被动响应数据包。 每个流表项包含匹配字段&…

openflow阅读感悟

一、背景 随着网络的快速发展和普及&#xff0c;设备和协议的复杂性导致了网络实验的困难。当时&#xff0c;几乎没有实际方法可以在足够现实的环境中尝试新的网络协议&#xff0c;来自网络学术、产业界的大多数新想法都未经试用和测试。因此&#xff0c;人们普遍认为网络基础设…

OpenFlow概念

OpenFlow是一种网络通信协议&#xff0c;应用于SDN架构中控制器和转发器之间的通信。软件定义网络SDN的一个核心思想就是“转发、控制分离”&#xff0c;要实现转、控分离&#xff0c;就需要在控制器与转发器之间建立一个通信接口标准&#xff0c;允许控制器直接访问和控制转发…

OpenFlow总结

OpenFlow总结 OpenFlow体系结构OpenFlow端口1.1、物理端口1.2、逻辑端口1.3、预定端口&#xff08;OpenFlow1.5中文版&#xff09; OpenFlow流表&#xff08;FlowTable&#xff09;2.1、概念2.2、流表结构 OpenFlow通信通道3.1、消息类型3.2 、消息交换 OpenFlow体系结构 Open…

Openflow

1.Openflow是啥 OpenFlow是第一个开放的南向接口协议&#xff0c;也是目前最流行的南向协议。 它提出了控制与转发分离的架构&#xff0c;规定了SDN转发设备的基本组件和功能要求&#xff0c;以及与控制器通信的协议。 2.OpenFlow组件 2.1. OpenFlow交换协议 2.2 OpenFlow网…