美文网首页unity网络编程
Unity高级(1)-服务器与网络交互

Unity高级(1)-服务器与网络交互

作者: 元宇宙协会 | 来源:发表于2018-10-30 10:33 被阅读83次

    PS
    配合整篇文章的视频讲解,可以登陆网易云课堂搜索:雷潮课堂,同时加入开发者群:134688909,群里人数突破400人,一起学习一起进步!

    可以课程搜索雷潮课堂也可以网校搜索雷潮课堂
    什么是网络
    • 网络概念

    网络应用 = 良好的UI + 良好的用户体验 + 实时更新的数据(弱联网、强联网)
    新闻:网易新闻、新浪新闻、搜狐新闻、腾讯新闻
    视频:优酷土豆、腾讯视频、搜狐视频、爱奇艺视频
    音乐:QQ音乐、百度音乐、酷狗音乐、酷我音乐
    LBS:百度地图、高德地图、大众点评、墨迹天气、滴滴打车
    电商:淘宝、京东商城、天猫、蘑菇街、凡客诚品、美丽说
    社交:QQ、微信、微博、陌陌、比邻
    游戏:王者荣耀,天天飞车,刀塔传奇,梦幻西游,大唐
    通过网络跟外界进行数据交互、数据更新,应用才能保持新鲜、活力


    客户端(Client):应用(iOS、android,windows等应用)
    服务器(Server):为客户端提供服务、提供数据、提供资源的机器
    请求(Request):客户端向服务器索取数据的一种行为
    响应(Response):服务器对客户端的请求做出的反应,一般指返回数据给客户端
    
    • 什么是服务器
      按照客户端开发阶段来分,服务器可以大致分为2种

    远程服务器
    别名:外网服务器、正式服务器
    使用阶段:应用上线后使用的服务器
    使用人群:供全体用户使用
    速度:取决于服务器的性能、用户的网速

    本地服务器
    别名:内网服务器、测试服务器
    使用阶段:应用处于开发、测试阶段使用的服务器
    使用人群:仅供公司内部的开发人员、测试人员使用
    速度:由于是局域网,所以速度飞快,有助于提高开发测试效率

    如何定位服务器


    通过URL(网站地址)来定位服务器

    • 什么是URL

    URL的全称是Uniform Resource Locator(统一资源定位符
    通过1个URL,能找到互联网上唯一的1个资源
    URL就是资源的地址、位置,互联网上的每个资源都有一个唯一的URL

    URL的基本格式 = 协议://主机地址/路径
    http://www.jianshu.com/user/74372cf48f59/latest_articles
    https://img.haomeiwen.com/i642887/5dad9dda442b8e8b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

    • 什么是协议
      协议:不同的协议,代表着不同的资源查找方式、资源传输方式
      主机地址:存放资源的主机(服务器)的IP地址(域名)

    URL中常见的协议:
    HTTP
    超文本传输协议,访问的是远程的网络资源,格式是http:// https://
    http协议是在网络开发中最常用的协议
    file
    访问的是本地计算机上的资源,格式是file://(不用加主机地址)
    mailto
    访问的是电子邮件地址,格式是mailto:
    FTP
    访问的是共享主机的文件资源,格式是ftp:// 飞秋

    • HTTP/1.1协议

    HTTP/1.1协议中,定义了8种发送http请求的方法
    GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH
    根据HTTP协议的设计初衷,不同的方法对资源有不同的操作方式
    PUT :增
    DELETE :删
    POST:改
    GET:查
    最常用的是GET和POST(实际上GET和POST都能办到增删改查)
    要想使用GET和POST请求跟服务器进行交互,得先了解一个概念
    参数
    就是传递给服务器的具体数据,比如登录时的帐号、密码

    • Post与Get请求区别

    Get
    在请求URL后面以?的形式跟上发给服务器的参数,多个参数之间用&隔开,比如
    http://www.test.com/login?username=leichao&id=888&type=JSON
    由于浏览器和服务器对URL长度有限制,因此在URL后面附带的参数是有限制的,通常不能超过1KB
    Post
    发给服务器的参数全部放在请求体中
    理论上,POST传递的数据量没有限制(具体还得看服务器的处理能力)
    选择GET和POST的建议
    如果要传递大量数据,比如文件上传,只能用POST请求
    GET的安全性比POST要差些,如果包含机密\敏感信息,建议用POST
    如果仅仅是索取数据(数据查询),建议使用GET
    如果是增加、修改、删除数据,建议使用POST

    • 响应头与相应体

    客户端向服务器发送请求,服务器应当做出响应,即返回数据给客户端
    HTTP协议规定:1个完整的HTTP响应中包含以下内容
    响应头:包含了对服务器的描述、对返回数据的描述

    HTTP/1.1 200 OK // 包含了HTTP协议版本、状态码、状态英文名称
    Server: Apache-Coyote/1.1 // 服务器的类型
    Content-Type: image/jpeg // 返回数据的类型
    Content-Length: 56811 // 返回数据的长度
    Date: Mon, 23 Jun 2014 12:54:52 GMT // 响应的时间
    响应体:服务器返回给客户端的具体数据,比如文件数据


    • 网络状态码


      常用的,其他的请自行查询
    Unity中的WWW

    WWW用于下载资源和打开一个Web网站,包含:Get/Post请求,本地资源文件下载,服务器资源下载。关于使用www方式加载AssetBundle资源,可以关注文章AssetBundle使用

    • Get
      1.一个链接中,参数是包括在链接中的,链接中的?后面都是参数;
      2.服务器不会自动分配空间,传输的内容会比较小。
    • Post
      1.参数在表单里面。
      2.服务器在底层检测到是Post请求,则会自动分配一个大的空间
      3.例如声音,视频等比较大的数据
    • WWW的使用
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class LoginWWW : MonoBehaviour {
    
        string url;
        public Image img;
        //public InputField put;
        void Start () {
            url = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1540877217182&di=9d56ef557a007c78b543278db41cbb28&imgtype=0&src=http%3A%2F%2Fb.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2Fd6ca7bcb0a46f21fd757a52ffb246b600c33ae6f.jpg";
            // Get
            StartCoroutine(GetLoadBg(url));
    
            // Post  请求头,请求体
            //Dictionary<string, string> dic = new Dictionary<string, string>();
            //dic.Add("uEmail", "136087399@qq.com");
            //dic.Add("uPwd", "1314521");
            //StartCoroutine(PostLoadLogin(url,dic));
        }
    
        // Get
        IEnumerator GetLoadBg(string url)
        {
            WWW w = new WWW(url);
            yield return w;
            // 返回字节数的长度
            //Debug.Log(w.size);
            // 打印响应头
            //foreach (var item in w.responseHeaders)
            //{
            //    Debug.Log(item);
            //}
            //  错误为空 ||下载完毕 || 图片下载完毕
            if (w.error == null || w.isDone == true || w.progress == 1)
            {
                img.sprite = Sprite.Create(w.texture, new Rect(0, 0, Screen.width, Screen.height), new Vector2(0.5f, 0.5f));
            }
            else
            {
                Debug.Log(w.error);
            }
        }
    
        // Post
        IEnumerator PostLoadLogin(string url, Dictionary<string, string> dic)
        {
            WWWForm f = new WWWForm();
            foreach (KeyValuePair<string,string> item in dic)
            {
                f.AddField(item.Key, item.Value);
            }
            WWW w = new WWW(url,f);
            yield return w;
            if (w.isDone)
            {
                if (w.error == null)
                {
                    Debug.Log("加载成功");
                }
                else
                {
                    Debug.Log(w.error);
                }
            }
            else
            {
                Debug.Log("正在下载");
            }
        }
    }
    
    网络-UnityWebRequest
    • Unity中使用WWW和C#中的HttpWebRequest方式进行下载。上面我们讲过WWW方式,这里我们不讲解HttpWebRequest,但是记住如果使用HttpWebRequest方式进行下载,要注意:
      在Unity中,使用system.net中的HttpWebRequest获取返回信息,如果数据较大,会卡顿,主要由于unity单线程,httpwebrequest不能异步执行;
      5.2版本后,Unity采用了UnityWebRequest 类,利用HTTP 协议和服务器交互,通常是通过 GET 和 POST 两种方式来对数据进行获取和提交。
      UnityWebRequest 由三个元素组成。
      ◾UploadHandler 处理数据 将数据发送到服务器 的对象
      ◾DownloadHandler 从服务器接收数据 的对象
      ◾UnityWebRequest 负责 HTTP 通信流量控制来管理上面两个对象的对象。

    GET

    public class LoginWebRequist : MonoBehaviour {
        string url;
        public RawImage img;
        void Start () {
            url = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1540877217182&di=9d56ef557a007c78b543278db41cbb28&imgtype=0&src=http%3A%2F%2Fb.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2Fd6ca7bcb0a46f21fd757a52ffb246b600c33ae6f.jpg";
            StartCoroutine(LoadImage(url));
        }
        IEnumerator LoadImage(string url)
        {   
            UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
            // DownloadHandlerTexture downloadTexture = new DownloadHandlerTexture(true);
            yield return www.SendWebRequest();
            Debug.Log(www.downloadHandler.data.Length);
            if (www.isHttpError)
            {
    
            }
            else
            {
                if (www.responseCode == 200)
                {
                    Debug.Log("连接成功");
                    //byte[] result = www.downloadHandler.data;
                    //int width = 0, height = 0;
                    //Texture2D t = new Texture2D(width,height);
                    //t.LoadImage(result);
                    //img.texture = t;
                    img.texture = DownloadHandlerTexture.GetContent(www);
                }
                else {
                    Debug.Log("连接不成功");
                    // 请检查网络,或者重新刷新
                }       
            }
        }
    }
    

    POST

     void Start() {  
            StartCoroutine( PostUrl(url, postData));        
        }  
    public IEnumerator PostUrl(string url, string postData)
        {
            using (UnityWebRequest www = new UnityWebRequest(url,"POST"))
            {
                // 上传请求头,byte[]数组
                byte[] postBytes = System.Text.Encoding.UTF8.GetBytes(postData);
                www.uploadHandler = (UploadHandler)new UploadHandlerRaw(postBytes);
                www.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
                www.SetRequestHeader("Content-Type", "application/json");
                yield return www.Send();
                if (www.isError)
                {
                    Debug.Log(www.error);
                }
                else
                {
                    // Show results as text  
                    if (www.responseCode == 200)
                    {
                        Debug.Log(www.downloadHandler.text);
                    }
                }
            }
        }
    
    • 服务器返回数据解析案例(Get)

    Json解析


    展示模板
    using LitJson;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    using UnityEngine.Networking;
    using UnityEngine.UI;
    
    public class JsonRead : MonoBehaviour {
    
        public People[] p;
        public People p1,p2,p3;
        public Text[] nameA;
        public Text[] ageA;
        public RawImage[] imgA;
        void Start () {
            p = new People[] {
             p1 = new People(),
             p2 = new People(),
             p3 = new People()
            };
            // 内容获取到了
            ReadJson();
        
            ShowPeople(0);
            ShowPeople(1);
            ShowPeople(2);
        }
    
        public void ShowPeople(int id)
        {
            nameA[id].text = p[id].name;
            ageA[id].text = p[id].age.ToString();  
            StartCoroutine(LoadImage(p[id].imgUrl, id));       
        }
    
      
        public void ReadJson()
        {
            string path = "Assets/Resources/TextFile.txt";
            string textOne = File.ReadAllText(path);
            JsonData data = JsonMapper.ToObject(File.ReadAllText(path));
            for (int i = 0; i < data.Count; i++)
            {
                JsonData idValue = data[i]["id"];
                p[i].id = int.Parse(idValue.ToString());
                JsonData AgeValue = data[i]["age"];
                p[i].age = int.Parse(AgeValue.ToString());
                JsonData nameValue = data[i]["name"];
                p[i].name = nameValue.ToString();
                JsonData imgUrlValue = data[i]["img"];
                p[i].imgUrl = imgUrlValue.ToString();
                Debug.Log("imgUrl :" + imgUrlValue.ToString());       
            }    
        }
    
        IEnumerator LoadImage(string url,int id)
        {
            UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
            yield return www.SendWebRequest();
            if (www.isHttpError)  {
                Debug.Log("连接错误");
            }
            else{
                if (www.responseCode == 200)
                {
                    Debug.Log("连接成功");
                    imgA[id].texture = DownloadHandlerTexture.GetContent(www);            
                }else            {
                    Debug.Log("连接不成功");
                    // 请检查网络,或者重新刷新
                }
            }
        }
    }
    
    public class People
    {
        public int id;
        public string name;
        public int age;
        public string imgUrl;
        public People()
        {
        }
        public People(int ID,string Name,int Age,string ImgUrl, Texture2D Img)
        {
            id = ID;
            name = Name;
            age = Age;
            imgUrl = ImgUrl;
            img = Img;
        }
    }
    
    • Json数据文本TextFile
    [
    {"id" : 1,"name" : "jame","age":20,"img":"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1541066018995&di=98ec0d44536d82fa03ac7a2580990afc&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201602%2F06%2F20160206025901_JtzEC.thumb.700_0.jpeg"},
    {"id" : 2,"name" : "Sume","age":22,"img":"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1541068738551&di=d2a0b0fa09fecbb87926dd7f64e5851f&imgtype=0&src=http%3A%2F%2Fimg5q.duitang.com%2Fuploads%2Fblog%2F201311%2F30%2F20131130235032_tBLEJ.thumb.700_0.jpeg"},
    {"id" : 3,"name" : "Baye","age":25,"img":"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1541066038599&di=74d1aaf46dd716863a187b7952fe1072&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F7c1ed21b0ef41bd52a1399d25bda81cb39db3d57.jpg"}
    ]
    
    • 斗鱼API请求实战
    加载出来斗鱼首页的房间
    http://capi.douyucdn.cn/api/v1/live?limit=20&offset=0 
    
    using LitJson;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Networking;
    using UnityEngine.UI;
    
    public class Root
    {
        /// <summary>
        /// 
        /// </summary>
        public int error { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public List<DataItem> data { get; set; }
    
        public Root()
        {
            data = new List<DataItem>();
        }
    }
    
    public class DataItem
    {
        /// <summary>
        /// 
        /// </summary>
        public string room_id { get; set; }
        /// <summary>
        ///   
        /// </summary>
        public string room_src { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string vertical_src { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int isVertical { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int cate_id { get; set; }
        /// <summary>
        /// 明天15:00总决赛 IGvsFNC
        /// </summary>
        public string room_name { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string show_status { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string subject { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string show_time { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string owner_uid { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string specific_catalog { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string specific_status { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string vod_quality { get; set; }
        /// <summary>
        /// 英雄联盟官方赛事
        /// </summary>
        public string nickname { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int online { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int hn { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string url { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string game_url { get; set; }
        /// <summary>
        /// 英雄联盟
        /// </summary>
        public string game_name { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int child_id { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string avatar { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string avatar_mid { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string avatar_small { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string jumpUrl { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string fans { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int ranktype { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int is_noble_rec { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string anchor_city { get; set; }
    }
    
    public class LoadData : MonoBehaviour {
        // https://rpic.douyucdn.cn/asrpic/181102/1863767_1328_66.jpg/dy1
        // https:\/\/rpic.douyucdn.cn\/asrpic\/181102\/1863767_1328_66.jpg\/dy1
        public Root rt;
        public DataItem item;
        public Text roomName;
        public Text gameName;
        public Text manName;
        public Text onlineCount;
        void Start() {
            rt = new Root();
    
            string url = "http://capi.douyucdn.cn/api/v1/live?limit=2&offset=0";
            StartCoroutine(GetLoadRoom(url,0));   
        }
    
        public void ShowRoomMessage(int RoomID)
        {
            DataItem item = rt.data[RoomID];
            Debug.Log(item.room_name);
            roomName.text = item.room_name;
            gameName.text = item.game_name;
            onlineCount.text = item.online.ToString();
            manName.text = item.nickname;
        }
    
        IEnumerator GetLoadRoom(string url,int RoomID)
        {
            UnityWebRequest q = UnityWebRequest.Get(url);
            yield return q.SendWebRequest();
            if (q.isNetworkError)
            {
            }
            else
            {
                string str = System.Text.Encoding.Default.GetString(q.downloadHandler.data);                 
                JsonData dataJson = JsonMapper.ToObject(str);  
                // 获取 data数组内容
                for (int i = 0; i < dataJson.Count; i++)
                {
                    JsonData errorValue = dataJson["error"];
                    //赋值给rt.error
                    rt.error = int.Parse(errorValue.ToString());
                    JsonData dataList = dataJson["data"][i];
                    Debug.Log(dataList.Count);
                    rt.data.Add(JsonMapper.ToObject<DataItem>(dataList.ToJson()));              
                }
                //roomName.text = rt.data[RoomID].room_name;
                //gameName.text = rt.data[RoomID].game_name;
                //onlineCount.text = rt.data[RoomID].online.ToString();
                //manName.text = rt.data[RoomID].nickname;
                ShowRoomMessage(RoomID);
            }
        }
    }
    
    
    • XML解析

    全称是Extensible Markup Language,译作“可扩展标记语言”
    跟JSON一样,也是常用的一种用于交互的数据格式
    一般也叫XML文档(XML Document)

    <photos>
        <photo name="全家福 第01张" height="80" />
        <photo name="全家福 第02张" hright="90" />
        <photo name="全家福 第03张" hright="60" />
    </photos>
    
    • 什么是XML,详细见文章XML介绍
    • XML的解析方式有2种
      DOM:一次性将整个XML文档加载进内存,比较适合解析小文件
      SAX:从根元素开始,按顺序一个元素一个元素往下解析,比较适合解析大文件
    XmlDocument
    - CreatElement() : //创建一个元素
    - AppendChild():  //往节点下追加根节点
    - Save() //保存XML文件
    XmlDeclaration
    - CreatXMLDeclaration() // 创建XML的声明节点
    XmlElement
    -GetElementsByTagName() // 根据节点名称获取下面的该节点名称的子节点元素
    -setAttribute() // 设置元素的属性
    -GetAttribute() // 获得元素的属性
    - InnetText
    -InnerXML
    XmlNode(XmlElement的基类)
    XmlNodeList
    
    • XML数据
    <Persones>
      <Person>
          <id> 1 </id>
          <name lang = “En”> jim</name>
          <damage> 100</damage>
      </Person>
       ...
    </Persones>
    
    • C#解析
    calss Person
    {
        public int ID {get;set;}
        public string Name{get;set;}
        public string Lang{get;set;}
        public int Damage{get; set;}
        public override string ToString() 
        {
           rerturn string.Format(“id:{0},Name:{1},Lang:{2},Damage:{3}”,ID,Name,Lang,Damage);
         }
    }
    

    PS
    配合整篇文章的视频讲解,可以登陆网易云课堂搜索:雷潮课堂,同时加入开发者群:134688909,群里人数突破400人,一起学习一起进步!

    可以课程搜索雷潮课堂也可以网校搜索雷潮课堂

    相关文章

      网友评论

        本文标题:Unity高级(1)-服务器与网络交互

        本文链接:https://www.haomeiwen.com/subject/wsswtqtx.html