Unity高級-HTTP

什么是HTTP

HTTP協(xié)議即超文本傳送協(xié)議(Hypertext Transfer Protocol ),是Web聯(lián)網(wǎng)的基礎,也是手機聯(lián)網(wǎng)常用的協(xié)議之一,HTTP協(xié)議是建立在TCP協(xié)議之上的一種應用。
HTTP連接最顯著的特點是客戶端發(fā)送的每次請求都需要服務器回送響應,在請求結(jié)束后,會主動釋放連接。由于HTTP在每次請求結(jié)束后都會主動釋放連接,因此HTTP連接是一種“短連接”。

什么是TCP

TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,由IETF的RFC 793定義。在簡化的計算機網(wǎng)絡OSI模型中,它完成第四層傳輸層所指定的功能,用戶數(shù)據(jù)報協(xié)議(UDP)是同一層內(nèi)另一個重要的傳輸協(xié)議。在因特網(wǎng)協(xié)議族(Internet protocol suite)中,TCP層是位于IP層之上,應用層之下的中間層。不同主機的應用層之間經(jīng)常需要可靠的、像管道一樣的連接,但是IP層不提供這樣的流機制,而是提供不可靠的包交換。

  • 互聯(lián)網(wǎng)的5層協(xié)議


    Protocols.png

它們叫什么名字,其實并不重要。只需要知道,互聯(lián)網(wǎng)分成若干層就可以了。
每一層都是為了完成一種功能。為了實現(xiàn)這些功能,就需要大家都遵守共同的規(guī)則。
大家都遵守的規(guī)則,就叫做"協(xié)議"(protocol)。


Get和Post請求

Http定義了與服務器交互的不同方法,最基本的方法有4種,分別是GET,POST,PUT,DELETE。URL全稱是資源描述符,我們可以這樣認為:一個URL地址,它用于描述一個網(wǎng)絡上的資源,而HTTP中的GET,POST,PUT,DELETE就對應著對這個資源的查,改,增,刪4個操作。到這里,大家應該有個大概的了解了,GET一般用于獲取/查詢資源信息,而POST一般用于更新資源信息。

上面大概說了一下HTTP規(guī)范中GET和POST的一些原理性的問題。但在實際的做的時候,很多人卻沒有按照HTTP規(guī)范去做,導致這個問題的原因有很多。
比如說:
1.很多人貪方便,更新資源時用了GET,因為用POST必須要FORM(表單),這樣會麻煩一點。
2.對資源的增,刪,改,查操作,其實都可以通過GET/POST完成,不需要用到PUT和DELETE。

Get和Post區(qū)別

  • 1.請求數(shù)據(jù):
    GET提交,請求的數(shù)據(jù)會附在URL之后(就是把數(shù)據(jù)放置在HTTP協(xié)議頭中),以?分割URL和傳輸數(shù)據(jù),多個參數(shù)用&連接;例 如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0 %E5%A5%BD。如果數(shù)據(jù)是英文字母/數(shù)字,原樣發(fā)送,如果是空格,轉(zhuǎn)換為+,如果是中文/其他字符,則直接把字符串用BASE64加密,得出如: %E4%BD%A0%E5%A5%BD,其中%XX中的XX為該符號以16進制表示的ASCII。
    POST提交:把提交的數(shù)據(jù)放置在是HTTP包的包體中。上文示例中斜體字就是實際的傳輸數(shù)據(jù),因此,GET提交的數(shù)據(jù)會在地址欄中顯示出來,而POST提交,地址欄不會改變。

  • 2.傳輸數(shù)據(jù)的大?。?br> 首先聲明:HTTP協(xié)議沒有對傳輸?shù)臄?shù)據(jù)大小進行限制,HTTP協(xié)議規(guī)范也沒有對URL長度進行限制。
    而在實際開發(fā)中存在的限制主要有:
    GET:特定瀏覽器和服務器對URL長度有限制,例如 IE對URL長度的限制是2083字節(jié)(2K+35)。對于其他瀏覽器,如Netscape、FireFox等,理論上沒有長度限制,其限制取決于操作系 統(tǒng)的支持。因此對于GET提交時,傳輸數(shù)據(jù)就會受到URL長度的 限制。
    POST:由于不是通過URL傳值,理論上數(shù)據(jù)不受 限。但實際各個WEB服務器會規(guī)定對post提交數(shù)據(jù)大小進行限制,Apache、IIS6都有各自的配置。

  • 3.安全性:
    POST的安全性要比GET的安全性高。比如:通過GET提交數(shù)據(jù),用戶名和密碼將明文出現(xiàn)在URL上,因為(1)登錄頁面有可能被瀏覽器緩存, (2)其他人查看瀏覽器的歷史紀錄,那么別人就可以拿到你的賬號和密碼了,除此之外,使用GET提交數(shù)據(jù)還可能會造成Cross-site request forgery攻擊。

HTTP請求方式

1.WWW

WWW是Unity給我們提供的網(wǎng)絡訪問類,它實現(xiàn)了ftp://http:// 、 https://三種協(xié)議,可以滿足我們再Unity的一些基本的網(wǎng)絡請求,并且使用了協(xié)程,用戶使用更加方便。

unity www 類同樣對應兩種提交數(shù)據(jù)的方式,常用的兩個構(gòu)造函數(shù)為:
static function WWW (url : String) : WWW
static function WWW (url : String, form : WWWForm) : WWW
第一個函數(shù)是通過get方法向服務器發(fā)送數(shù)據(jù),第二個是用post提交數(shù)據(jù),其中WWWForm有個方法叫:AddField(agr : string, value : string),來添加參數(shù)。

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 協(xié)議和服務器交互,通常是通過 GET 和 POST 兩種方式來對數(shù)據(jù)進行獲取和提交。下面對這兩種方式進行一下說明:

GET 方式:
GET 方式通過在網(wǎng)絡地址附加參數(shù)來完成數(shù)據(jù)的提交,比如在地址 http://www.jb51.net/?name=test 中,前面部分 http://www.jb51.net表示數(shù)據(jù)提交的網(wǎng)址,后面部分 name=test 表示附加的參數(shù),其中 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())
{
    //對接收到的內(nèi)容進行處理
    Stream respStream = wr.GetResponseStream();  
    StreamReader reader = new StreamReader(respStream, Encoding.UTF8);  
    string result = reader.ReadToEnd();  
}

POST 方式:
POST 方式通過在頁面內(nèi)容中填寫參數(shù)的方法來完成數(shù)據(jù)的提交,參數(shù)的格式和 GET 方式一樣,是類似于 "username=test&password=123456" 這樣的結(jié)構(gòu)。

程序代碼如下:

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())
{
    //對接收到的內(nèi)容進行處理
    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 標識的資源發(fā)送數(shù)據(jù)和從 URI 標識的資源接收數(shù)據(jù)的公共方法, WebClient 類提供向 URI 標識的任何本地、Intranet 或 Internet 資源發(fā)送數(shù)據(jù)以及從這些資源接收數(shù)據(jù)的公共方法。
\WebClient 類使用 WebRequest 類提供對資源的訪問。WebClient 實例可以通過任何已向 WebRequest.RegisterPrefix 方法注冊的 WebRequest 子代訪問數(shù)據(jù)。默認情況下,WebClient 實例不發(fā)送可選的 HTTP 報頭。
如果您的請求需要可選報頭,必須將該報頭添加到 Headers 集合。例如,要在響應中保留查詢,必須添加用戶代理報頭。此外,如果用戶代理標頭丟失,服務器可能返回 500(內(nèi)部服務器錯誤)。
在 WebClient 實例中,AllowAutoRedirect 設置為 true。

查看MSND上對webclient的解釋,有上傳與下載方法:

  • WebClient提供一些上傳方法:


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


    image
  • WebClient與其他網(wǎng)絡相關類的區(qū)別
    WebClient和HttpWebRequst是用來獲取數(shù)據(jù)的2種方式,一般而言,WebClient更傾向于“按需下載”,事實上掌握它也是相對容易的,而HttpWebRequst則允許你設置請求頭或者對內(nèi)容需要更多的控制,
    后者有點類似于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;
        }
    }
}
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容