什么是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;
}
}
}
