Unity高级-HTTP

什么是HTTP

HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”。

什么是TCP

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内另一个重要的传输协议。在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。

  • 互联网的5层协议


    Protocols.png

它们叫什么名字,其实并不重要。只需要知道,互联网分成若干层就可以了。
每一层都是为了完成一种功能。为了实现这些功能,就需要大家都遵守共同的规则。
大家都遵守的规则,就叫做"协议"(protocol)。


Get和Post请求

Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作。到这里,大家应该有个大概的了解了,GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。

上面大概说了一下HTTP规范中GET和POST的一些原理性的问题。但在实际的做的时候,很多人却没有按照HTTP规范去做,导致这个问题的原因有很多。
比如说:
1.很多人贪方便,更新资源时用了GET,因为用POST必须要FORM(表单),这样会麻烦一点。
2.对资源的增,删,改,查操作,其实都可以通过GET/POST完成,不需要用到PUT和DELETE。

Get和Post区别

  • 1.请求数据:
    GET提交,请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,多个参数用&连接;例 如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0 %E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如: %E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。
    POST提交:把提交的数据放置在是HTTP包的包体中。上文示例中斜体字就是实际的传输数据,因此,GET提交的数据会在地址栏中显示出来,而POST提交,地址栏不会改变。

  • 2.传输数据的大小:
    首先声明:HTTP协议没有对传输的数据大小进行限制,HTTP协议规范也没有对URL长度进行限制。
    而在实际开发中存在的限制主要有:
    GET:特定浏览器和服务器对URL长度有限制,例如 IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系 统的支持。因此对于GET提交时,传输数据就会受到URL长度的 限制。
    POST:由于不是通过URL传值,理论上数据不受 限。但实际各个WEB服务器会规定对post提交数据大小进行限制,Apache、IIS6都有各自的配置。

  • 3.安全性:
    POST的安全性要比GET的安全性高。比如:通过GET提交数据,用户名和密码将明文出现在URL上,因为(1)登录页面有可能被浏览器缓存, (2)其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用GET提交数据还可能会造成Cross-site request forgery攻击。

HTTP请求方式

1.WWW

WWW是Unity给我们提供的网络访问类,它实现了ftp://http://https://三种协议,可以满足我们再Unity的一些基本的网络请求,并且使用了协程,用户使用更加方便。

unity www 类同样对应两种提交数据的方式,常用的两个构造函数为:
static function WWW (url : String) : WWW
static function WWW (url : String, form : WWWForm) : WWW
第一个函数是通过get方法向服务器发送数据,第二个是用post提交数据,其中WWWForm有个方法叫:AddField(agr : string, value : string),来添加参数。

get例子:

privatevar url : String = "127.0.0.1/login.php?user=test&pwd=123";  
function Start () {  
     WWW www= WWW(url);  
     yield return www;       
     if(www.error != null) {  
          Debug.Log(www.error);  
     }   else {  
          Debug.Log(www.text);  
     }  
}  
post例子:

privatevar url : String = "127.0.0.1/login.php";  
function Start () {  
     WWWForm form = new WWWForm();  
     form.AddField("user", "test");  
     form.AddField("pwd", "123");  

     WWW www= WWW(url, form);  
     yield return www;  
     if(www.error != null) {  
          Debug.Log(www.error);  
     }   else {  
          Debug.Log(www.text);  
     }  
}  

2.HttpWebRequest

HttpWebRequest类是C#为我们提供的一个类,主要利用HTTP 协议和服务器交互,通常是通过 GET 和 POST 两种方式来对数据进行获取和提交。下面对这两种方式进行一下说明:

GET 方式:
GET 方式通过在网络地址附加参数来完成数据的提交,比如在地址 http://www.jb51.net/?name=test 中,前面部分 http://www.jb51.net表示数据提交的网址,后面部分 name=test 表示附加的参数,其中 name 表示一个键(key), test 表示这个键对应的值(value)。

程序代码如下:

string url="http://www.jb51.net?hl=zh-CN";
HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create( url );
req.Method = "GET";
using (WebResponse wr = req.GetResponse())
{
    //对接收到的内容进行处理
    Stream respStream = wr.GetResponseStream();  
    StreamReader reader = new StreamReader(respStream, Encoding.UTF8);  
    string result = reader.ReadToEnd();  
}

POST 方式:
POST 方式通过在页面内容中填写参数的方法来完成数据的提交,参数的格式和 GET 方式一样,是类似于 "username=test&password=123456" 这样的结构。

程序代码如下:

HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create( "http://www.jb51.net/" );
req.Method = "POST";

//拼接Form表单里的信息
string requestForm = "username=test&password=123456";     
byte[] bs = Encoding.ASCII.GetBytes(requestForm);
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = bs.Length;
using (Stream reqStream = req.GetRequestStream())
{  
   //往请求流中写入表单
   reqStream.Write(bs, 0, bs.Length);
}

using (WebResponse wr = req.GetResponse())
{
    //对接收到的内容进行处理
    Stream respStream = wr.GetResponseStream();  
    StreamReader reader = new StreamReader(respStream, Encoding.UTF8);  
    string result = reader.ReadToEnd();  
}

异步读取方式

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

public class TestHttpAsyc : MonoBehaviour
{
    public Image img;
    bool success;
    byte[] buffer = new byte[1024];

    FileStream fileStream;
    HttpWebRequest request;
    HttpWebResponse response;
    Stream stream;
    int readCount;

    void Start()
    {
        fileStream = new FileStream("D:/abc.png", FileMode.Create);
        string url = "http://pic4.nipic.com/20091121/3764872_215617048242_2.jpg";
        request = (HttpWebRequest)WebRequest.Create(url);
        request.Method = "GET";
        request.BeginGetResponse(new AsyncCallback(delegate (IAsyncResult result)
        {
            response = (HttpWebResponse)request.EndGetResponse(result);
            stream = response.GetResponseStream();
            stream.BeginRead(buffer, 0, 1024, new AsyncCallback(ReadCallBack), request);
        }), request);
    }
    
    void ReadCallBack(IAsyncResult result)
    {
        int read = stream.EndRead(result);
        readCount += read;

        if (read>0)
        {
            fileStream.Write(buffer, 0, 1024);
            fileStream.Flush();

            buffer = new byte[1024];
            stream.BeginRead(buffer, 0, 1024, new AsyncCallback(ReadCallBack), request);
        }
        if(readCount>= response.ContentLength)
        {
            fileStream.Close();
            response.Close();
            stream.Close();
            success=true;
        }
    }

    void Update()
    {
        if (success)
        {
            success = false;
            Texture2D t2d = new Texture2D(512, 512);
            t2d.LoadImage(buffer);

            Rect rect = new Rect(0, 0, t2d.width, t2d.height);
            Sprite sp = Sprite.Create(t2d, rect, Vector2.one * 0.5f);
            img.sprite = sp;
        }
    }
}

3.WebClient

WebClient提供向 URI 标识的资源发送数据和从 URI 标识的资源接收数据的公共方法, WebClient 类提供向 URI 标识的任何本地、Intranet 或 Internet 资源发送数据以及从这些资源接收数据的公共方法。
\WebClient 类使用 WebRequest 类提供对资源的访问。WebClient 实例可以通过任何已向 WebRequest.RegisterPrefix 方法注册的 WebRequest 子代访问数据。默认情况下,WebClient 实例不发送可选的 HTTP 报头。
如果您的请求需要可选报头,必须将该报头添加到 Headers 集合。例如,要在响应中保留查询,必须添加用户代理报头。此外,如果用户代理标头丢失,服务器可能返回 500(内部服务器错误)。
在 WebClient 实例中,AllowAutoRedirect 设置为 true。

查看MSND上对webclient的解释,有上传与下载方法:

  • WebClient提供一些上传方法:


    image
  • WebClient提供一些下载方法:


    image
  • WebClient与其他网络相关类的区别
    WebClient和HttpWebRequst是用来获取数据的2种方式,一般而言,WebClient更倾向于“按需下载”,事实上掌握它也是相对容易的,而HttpWebRequst则允许你设置请求头或者对内容需要更多的控制,
    后者有点类似于form中的submit。虽然两者都是异步请求事件,但是WebClient是基于事件的异步,而HttpWebRequst是基于代理的异步编程。

  • WebClient使用方法

using System.Net;
using System;
using System.IO;
public class TestWebClient : MonoBehaviour {

        string url = "http://e.hiphotos.baidu.com/zhidao/pic/item/a2cc7cd98d1001e98debe2acbc0e7bec55e797ba.jpg";
    void Start () {
        WebClient client = new WebClient();
        client.DownloadDataCompleted += DownloadDataCallback;
        client.DownloadProgressChanged += Client_DownloadProgressChanged;

        
        Uri uri = new Uri(url);
        client.DownloadDataAsync(uri);
    }
    //下载进度
    private void Client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        Debug.Log(e.BytesReceived * 100 / e.TotalBytesToReceive  + "%");
    }
    //下载完成
    void DownloadDataCallback(object sender, DownloadDataCompletedEventArgs data)
    {
        try{
            if (data.Result.Length > 0 && data.Error == null && data.Cancelled == false)
            {
                using (MemoryStream ms = new MemoryStream(data.Result))
                {
                    byte[] buffer = ms.ToArray();
                    string path = @"D:\Unity-Teacher\Teach_TCP\Assets/iamge.png";
                    File.WriteAllBytes(path, buffer);
                    Debug.Log("下载完成");
                }
            }
        } catch (Exception exception){
            throw exception;
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容