BestHttp介绍1
BestHttp 文档翻译
介绍
BestHTTP 是基于 RFC 2616 的 HTTP/1.1 实现 , 它支持几乎所有Unity移动和独立平台 (请参阅 Supported platforms).
我的目标是为Unity创建一个易于使用但功能强大的插件,以利用HTTP / 1.1中的潜力. 本文档是一个快速指南,并非所有功能和属性都可以在这里找到. 如需支持,功能请求或一般性问题,您可以发送电子邮件至besthttp@gmail.com.
快速入门
- 1:使用头文件.本文档中的所有示例都没有任何错误检查!在编写时,请确保添加一些空检查
 
        using BestHTTP;     
- 2:GET 请求,向Web服务器发出请求的最简单方法是创建一个HTTPRequest对象,为其构造函数提供url和回调函数.在我们构造一个新的HTTPRequest对象后,我们唯一需要做的就是使用Send()函数发送请求.
 
        {
                HTTPRequest request = new HTTPRequest(new Uri("https://google.com"), OnRequestFinished); request.Send(); 
                new HTTPRequest(new Uri("https://google.com"), (request, response) => Debug.Log("Finished!")).Send(); 
        }
        void OnRequestFinished(HTTPRequest request, HTTPResponse response) 
        {    
                Debug.Log("Request Finished! Text received: " + response.DataAsText); 
        }      
回调函数始终接收原始HTTPRequest对象和保存服务器响应的HTTPResponse对象。如果出现错误,则HTTPResponse对象为null,需要自己判断,并且请求对象具有Exception属性,该属性可能包含有关错误的额外信息(如果有).
虽然请求总是在不同的线程上处理,但调用回调函数已完成Unity的主线程,所以我们不必做任何线程同步。
- 3:其他请求 上面的例子是简单的GET请求。如果我们没有指定方法,默认情况下所有请求都将是GET请求。构造函数具有另一个参数,可用于指定请求的方法.
 
        HTTPRequest request = new HTTPRequest(new Uri("http://server.com/path"), HTTPMethods.Post, OnRequestFinished); 
        request.AddField("FieldName", "Field Value"); 
        request.Send();         
要在不设置字段的情况下POST任何数据,可以使用RawData属性
        HTTPRequest request = new HTTPRequest(new Uri("http://server.com/path"), HTTPMethods.Post, OnRequestFinished); 
        request.RawData =  Encoding.UTF8.GetBytes("Field Value"); 
        request.Send();         
有关其他样品,请查看Small Code-Samples部分。
除了GET和POST之外,您还可以使用 HEAD,PUT,DELETE,PATCH 方法:
        HTTPRequest request = new HTTPRequest(new Uri("http://server.com/path"), HTTPMethods.Head, OnRequestFinished); 
        request.Send(); 
        HTTPRequest request = new HTTPRequest(new Uri("http://server.com/path"), HTTPMethods.Put, OnRequestFinished); 
        request.Send(); 
        HTTPRequest request = new HTTPRequest(new Uri("http://server.com/path"), HTTPMethods.Delete, OnRequestFinished); 
        request.Send(); 
        HTTPRequest request = new HTTPRequest(new Uri("http://server.com/path"), HTTPMethods.Patch, OnRequestFinished); 
        request.Send(); 
- 4:如何使用下载的数据?可以从HTTPResponse对象的Data属性访问原始字节。我们来看一个如何下载图像的例子:
 
        new HTTPRequest(new Uri("http://yourserver.com/path/to/image.png"), (request, response) => 
                { 
                        var tex = new Texture2D(0, 0); 
                        tex.LoadImage(response.Data); 
                        guiTexture.texture = tex; 
                }).Send(); 
        new HTTPRequest(new Uri("http://yourserver.com/path/to/image.png"),
        (request, response) => guiTexture.texture = response.DataAsTexture2D).Send();   
除 response.DataAsTexture2D 外,还有一个 response.DataAsText 属性可将响应解码为Utf8字符串。将来可能会添加更多数据解码属性。如果您有任何想法,请自己添加吧.
- 5:替换 WWW,使用协程,一般不推荐使用这种方式
 
        HTTPRequest request = new HTTPRequest(new Uri("http://server.com"));
        request.Send(); 
        yield return StartCoroutine(request); 
        Debug.Log("Request finished! Downloaded Data:" + request.Response.DataAsText);  
高级用法
- 1:methodType,我们将向服务器发送什么样的请求。默认的methodType是HTTPMethods.Get
 - 2:IsKeepAlive:向服务器指示我们希望tcp连接保持打开状态,因此连续的http请求不需要再次建立连接。如果我们将它保留为默认值true,它可以为我们节省大量时间。如果我们知道我们不会使用通常会将其设置为false的请求。默认值是true。
 - 3:disableCache:告诉BestHTTP系统使用或完全跳过缓存机制。如果其值为true,则系统不会检查缓存中是否存储了响应,并且也不会保存响应。默认值为false
 - 4:请求一次:
 
        public static void RequestAsyncShort(string url, RequestCallBack callBack)
        {
                BestHTTP.HTTPRequest req = new HTTPRequest(new Uri(url), HTTPMethods.Get, 
                (originalRequest, response) =>
                {
                        if (originalRequest.State == HTTPRequestStates.Finished)
                        {
                        callBack((int) originalRequest.State, response.DataAsText);
                        }
                        else
                        {
                        callBack((int) originalRequest.State, "");
                        }
                });
                req.IsKeepAlive = false;
                req.DisableCache = true;
                req.Send();
        }           
- 5:Best HTTP通过HTTPRequest的Credentials属性支持Basic和Digest身份验证:
 
        using BestHTTP.Authentication; 
        var request = new HTTPRequest(new Uri("http://yourserver.org/auth-path"), (req, resp) => 
                { 
                        if (resp.StatusCode != 401) 
                                Debug.Log("Authenticated"); 
                        else 
                                Debug.Log("NOT Authenticated"); 
                        Debug.Log(resp.DataAsText); 
                }); 
        request.Credentials = new Credentials("usr", "paswd"); 
        request.Send();                 
- 6:下载流媒体(Download Streaming)
默认情况下,当完全下载并处理服务器的答案时,我们提供给HTTPRequest的构造函数的回调函数将只调用一次。这样,如果我们想要下载更大的文件,我们就会在移动设备上快速耗尽内存。我们的应用程序会崩溃,用户会对我们生气,应用程序会得到很多不好的评级。理所当然。为了避免这种情况,BestHTTP旨在非常容易地处理这个问题:只需将一个标志(属性)切换为true,每次下载预定义数据量时(指定内存中缓存多少字节量)都会调用我们的回调函数。此外,如果我们没有关闭缓存,下载的响应将被缓存,以便下次我们可以从本地缓存流式传输整个响应,而无需更改我们的代码,甚至无需访问Web服务器。 (备注:服务器必须发送有效的缓存头(“Expires”头:请参阅RFC以允许此操作。) 
        var request = new HTTPRequest(new Uri("http://yourserver.com/bigfile"), (req, resp) => 
        { 
                List<byte[]> fragments = resp.GetStreamedFragments(); 
                // Write out the downloaded data to a file: 
                using (FileStream fs = new FileStream("pathToSave", FileMode.Append)) {
                        foreach(byte[] data in fragments) fs.Write(data, 0, data.Length); 
                }
                if (resp.IsStreamingFinished) Debug.Log("Download finished!"); 
        }); 
        request.UseStreaming = true; 
        request.StreamFragmentSize = 1 * 1024 * 1024; // 1 megabyte
        request.DisableCache = true; // already saving to a file, so turn off caching request.Send(); 
1):我们将标志 - UseStreaming - 切换为true,因此我们的回调可能被调用多次。 2):StreamFragmentSize指示在调用回调之前我们想要在内存中缓冲的最大数据量。 3):每次下载StreamFragmentSize大小的块时都会调用我们的回调,并且当IsStreamingFinished设置为true时再调用一次。 4):要获取下载的数据,我们必须使用GetStreamedFragments()函数。我们应该将结果保存在临时变量中,因为在此调用中清除了内部缓冲区(返回字节量,清除内存,写入文件),因此连续调用将为我们提供null结果。 5):我们在此示例中禁用了缓存,因为我们已经保存了下载的缓存,保存在一个磁盘文件中,并且我们不想占用太多空间。
下载进度
        var request = new HTTPRequest(new Uri(address), OnFinished); 
        request.OnProgress = OnDownloadProgress; 
        request.Send(); 
        void OnDownloadProgress(HTTPRequest request, int downloaded, int length) 
        { 
                float progressPercent = (downloaded / (float)length) * 100.0f;
                Debug.Log("Downloaded: " + progressPercent.ToString("F2") + "%"); 
        } 
- 7:上传流媒体(Upload Streaming)
使用HTTPRequest对象的UploadStream属性设置上传的数据流Stream。当上传完成并且DisposeUploadStream为true时,插件将调用Stream流上的Dispose()函数。如果流的长度未知,则UseUploadStreamLength属性应设置为false。在这种情况下,插件将使用分块传输编码从流中发送数据: 
        var request = new HTTPRequest(new Uri(address), HTTPMethods.Post, OnUploadFinished); 
        request.UploadStream = new FileStream("File_To.Upload", FileMode.Open); 
        request.Send(); 
上传进度回调,要跟踪和显示上传进度,您可以使用HTTPRequest类的OnUploadProgress事件。 OnUploadProgress可以与RawData,表单(通过AddField和AddBinaryData)以及UploadStream一起使用。
        var request = new HTTPRequest(new Uri(address), HTTPMethods.Post, OnFinished); 
        request.RawData =  Encoding.UTF8.GetBytes("Field Value");
        request.OnUploadProgress = OnUploadProgress; 
        request.Send(); 
        void OnUploadProgress(HTTPRequest request, long uploaded, long length)
        { 
                float progressPercent = (uploaded / (float)length) * 100.0f;
                Debug.Log("Uploaded: " + progressPercent.ToString("F2") + "%"); 
        }
- 8:缓存
 
缓存也基于HTTP / 1.1 RFC。它使用标头来存储和验证响应。缓存机制在幕后工作,我们唯一要做的就是决定是否要启用或禁用它。如果缓存的响应具有带有未来日期的“Expires”标头,则BestHTTP将使用缓存的响应,而不对服务器进行验证。这意味着我们不必启动与服务器的任何tcp连接。这可以节省我们的时间,带宽和离线工作。 (这段话的意思相当于本地数据缓存,请求服务器,不会真的连接服务器,会从本地取出原来已经请求过的数据,只要这个数据没有过期,则直接返回给使用者)
虽然缓存是自动的,但我们可以控制它,或者我们可以使用HTTPCacheService类的公共函数获取一些信息:
1):BeginClear(),它将开始在单独的线程上清除整个缓存 2):BeginMaintainence(),有了这个函数的帮助,我们可以根据上次访问时间删除缓存的条目。它删除上次访问时间早于指定时间的条目。我们还可以使用此函数来控制缓存大小: HTTPCacheService.BeginMaintainence(new HTTPCacheMaintananceParams(TimeSpan.FromDays(14), 50 * 1024 * 1024)); 3):GetCacheSize(),将以字节为单位返回缓存的大小。 4):GetCacheEntryCount(),将返回缓存中存储的条目数。可以使用float avgSize = GetCacheSize()/(float)GetCacheEntryCount()公式计算平均缓存条目大小。
- 9:Cookie ,处理cookie操作对程序员来说是透明的。设置请求Cookie标头以及解析和维护响应的Set-Cookie标头由插件自动完成。有很多关于cookie的Global Settings 。有关详细信息,请参阅 Global Settings 部分。
它可以以各种方式控制 
1):使用每一次的请求对象HTTPRequest.IsCookiesEnabled属性以及全局的HTTPManager.IsCookiesEnabled属性来禁用 2):可以通过调用CookieJar.Clear()函数从Cookie Jar中删除Cookie 3):可以通过响应的Cookies属性访问从服务器发送的新cookie。
可以通过将Cookie添加到Cookie列表中将Cookie添加到HTTPRequest:
        var request = new HTTPRequest(new Uri(address), OnFinished);
        request.Cookies.Add(new Cookie("Name", "Value")); 
        request.Send(); 
这些cookie将与服务器发送的cookie合并。如果在请求或HTTPManager中将IsCookiesEnabled设置为false,则仅发送这些用户设置的cookie
- 10:代理,HTTPProxy对象可以设置为HTTPRequest的Proxy属性。这样,请求将通过给定的代理。
 
        request.Proxy = new HTTPProxy(new Uri("http://localhost:3128")); 
您也可以设置全局代理,因此您不必手动将其设置为所有请求。请参阅Global Settings一章
- 11:终止请求,您可以通过调用HTTPRequest对象的Abort()函数来中止正在进行的请求
 
        request = new HTTPRequest(new Uri("http://yourserver.com/bigfile"), (req, resp) => { ... }); 
        request.Send(); 
        // And after some time: 
        request.Abort(); //将调用回调函数,并且响应对象(resp)将为null。- 12:超时,2 种情况,第一种是:ConnectTimeout,使用此属性,您可以控制等待在应用程序和远程服务器之间建立连接的时间。其默认值为20秒
 
        request = new HTTPRequest(new Uri("http://yourserver.com/"), (req, resp) => { ... }); 
        request.ConnectTimeout = TimeSpan.FromSeconds(2); 
        request.Send(); 
第二种:Timeout 使用此属性,您可以控制等待处理请求的时间(此时已连接到服务器,正在等待服务器响应,发送请求和下载响应)。其默认值为60秒。
        request = new HTTPRequest(new Uri("http://yourserver.com/"), (req, resp) => { ... }); 
        request.Timeout = TimeSpan.FromSeconds(10); 
        request.Send(); 
        string url = "http://besthttp.azurewebsites.net/api/LeaderboardTest?from=0&count=10"; 
        HTTPRequest request = new HTTPRequest(new Uri(url), (req, resp) => 
        { 
                switch (req.State) 
                { 
                        // The request finished without any problem. 
                        case HTTPRequestStates.Finished: 
                                Debug.Log("Request Finished Successfully!\n" + resp.DataAsText); 
                                break; 
                                // The request finished with an unexpected error. 
                        // The request's Exception property may contain more information about the error. 
                        case HTTPRequestStates.Error: 
                                Debug.LogError("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception")); 
                        break; 
                        // The request aborted, initiated by the user. 
                        case HTTPRequestStates.Aborted: 
                                Debug.LogWarning("Request Aborted!"); 
                        break; 
                        // Ceonnecting to the server timed out. 
                        case HTTPRequestStates.ConnectionTimedOut: 
                                Debug.LogError("Connection Timed Out!"); 
                        break; 
                        // The request didn't finished in the given time. 
                        case HTTPRequestStates.TimedOut: 
                                Debug.LogError("Processing the request Timed Out!"); break; 
                } 
        }); 
        // Very little time, for testing purposes: 
        request.ConnectTimeout = TimeSpan.FromMilliseconds(2); 
        request.Timeout = TimeSpan.FromSeconds(5); 
        request.IsKeepAlive = false; 
        request.DisableCache = true; 
        request.Send(); 
- 13:Request States 请求状态,所有请求都有一个包含其内部状态的State属性。可能的状态如下:
 
1):Initial:请求的初始状态。使用此状态不会调用任何回调 2):Queued:在队列中等待处理。使用此状态不会调用任何回调 3):Processing:开始处理请求。在此状态下,客户端将发送请求,并解析响应。使用此状态不会调用任何回调。 4):Finished:请求完成没有问题。解析完成的响应后,可以使用结果。将使用有效的响应对象调用用户定义的回调。请求的Exception属性将为null。 5):Error:请求在插件中以意外错误结束。将使用null响应对象调用用户定义的回调。请求的Exception属性可能包含有关错误的更多信息,但它可以为null。 6):Aborted: 请求由客户端中止(HTTPRequest的Abort()函数)。将使用null响应调用用户定义的回调。请求的Exception属性将为null。 7):ConnectionTimedOut:连接到服务器超时。将使用null响应调用用户定义的回调。请求的Exception属性将为null。 8):TimedOut:请求未在给定时间内完成。将使用null响应调用用户定义的回调。请求的Exception属性将为null。
- 14:请求的优先级Request Priority ,可以通过HTTPRequest的Priority属性更改请求的优先级。与较低优先级请求相比,将从请求队列中选择更高优先级的请求。
 
        var request = new HTTPRequest(new Uri("https://google.com"), ...);
        request.Priority = -1; 
        request.Send(); 
- 15:服务器证书验证,Server Certificate Validation 可以通过实现ICertificateVerifyer接口并将其设置为HTTPRequest的CustomCertificateVerifyer来验证服务器发送的证书:
 
        using System; 
        using Org.BouncyCastle.Crypto.Tls; 
        using Org.BouncyCastle.Asn1.X509; 
        class CustomVerifier : ICertificateVerifyer 
        { 
                public bool IsValid(Uri serverUri, X509CertificateStructure[] certs) 
                { 
                // TODO: Return false, if validation fails return true; 
                } 
        } 
        var request = new HTTPRequest(new Uri("https://google.com"), ...);
        request.CustomCertificateVerifyer = new CustomVerifier(); 
        request.UseAlternateSSL = true; 
        request.Send(); 
- 16:控制重定向,Control Redirections ,重定向由插件自动处理,但有时我们必须在向我们重定向到的uri发出新请求之前进行更改。我们可以在HTTPRequest的OnBeforeRedirection事件处理程序中进行这些更改。在插件向新uri发出新请求之前调用此事件。函数的返回值将控制重定向:如果为false,则重定向将被中止,子线程中调用
 
        var request = new HTTPRequest(uri, HTTPMethods.Post); 
        request.AddField("field", "data"); 
        request.OnBeforeRedirection += OnBeforeRedirect; 
        request.Send(); 
        bool OnBeforeRedirect(HTTPRequest req, HTTPResponse resp, Uri redirectUri) 
        { 
                if (req.MethodType == HTTPMethods.Post && resp.StatusCode == 302) 
                { 
                        req.MethodType = HTTPMethods.Get; 
                        // Don't send more data than needed. 
                        // So we will delete our already processed form data.
                        req.Clear(); 
                } 
                return true; 
        } - 17:统计(Statistics),您可以使用HTTPManager.GetGeneralStatistics函数获取有关底层插件的一些统计信息:
 
        GeneralStatistics stats = HTTPManager.GetGeneralStatistics(StatisticsQueryFlags.All); Debug.Log(stats.ActiveConnections); 
1):Connections:将返回基于连接的统计信息。这些是以下内容: A:RequestsInQueue:队列中等待空闲连接的请求数。 B:Connections:插件跟踪的HTTPConnection实例数。这是以下所有连接的总和 B:ActiveConnections:活动连接数。这些连接当前正在处理请求。 C:FreeConnections:免费连接数。这些连接完成了请求,他们正在等待另一个请求或回收。 D:RecycledConnections:回收连接数。这些连接将尽快删除。 2):Cache:基于缓存的统计信息这些是以下内容: A:CacheEntityCount:缓存响应的数量。 B:CacheSize:缓存响应的总和大小 3):Cookie:基于Cookie的统计信息。这些是以下内容 A:CookieCount:Cookie Jar中的Cookie数量 B:CookieJarSize:Cookie Jar中Cookie的总和大小
Global Settings
- 1:使用以下属性,我们可以更改一些默认值,否则应在HTTPRequest的构造函数中指定。因此,大多数这些属性都是节省时间的快捷方式。
 - 2:这些更改将影响其值更改后创建的所有请求。可以通过HTTPManager类的静态属性更改默认值:
 
1):MaxConnectionPerServer:允许唯一主机的连接数。 http://example.org和https://example.org被视为两个独立的服务器。默认值为4。 2):KeepAliveDefaultValue:HTTPRequest的IsKeepAlive属性的默认值。如果IsKeepAlive为false,则将在每个请求之前设置与服务器的tcp连接,并在其之后立即关闭。如果连续请求很少,则应将其更改为false。赋予HTTPRequest构造函数的值将仅覆盖此请求的此值。默认值是true。 3):IsCachingDisabled:使用此属性,我们可以全局禁用或启用缓存服务。赋予HTTPRequest构造函数的值将仅覆盖此请求的此值。默认值是true。 4):MaxConnectionIdleTime:指定BestHTTP在完成最后一次请求后销毁连接之前应等待的空闲时间。默认值为2分钟。 5):IsCookiesEnabled:使用此选项,可以启用或禁用所有Cookie操作。默认值是true。 6):CookieJarSize:使用此选项可以控制Cookie存储的大小。默认值为10485760(10 MB). 7):EnablePrivateBrowsing:如果启用此选项,则不会将Cookie写入磁盘。默认值为false 8):ConnectTimeout:使用此选项,您可以设置HTTPRequests的默认ConnectTimeout值。默认值为20秒。 9):RequestTimeout:使用此选项,您可以设置HTTPRequests.Timeout的默认超时值。默认值为60秒。 10):RootCacheFolderProvider:默认情况下,插件会将所有缓存和cookie数据保存在Application.persistentDataPath返回的路径下。您可以为此委托指定一个函数,以返回自定义根路径以定义新路径。这个代理将在子线程上调用! 11):Proxy:所有HTTPRequests的全局默认代理。 HTTPRequest的代理仍然可以按请求进行更改。默认值为null 12):Logger:ILogger实现,能够控制将记录有关插件内部的信息,以及如何记录这些信息 13):DefaultCertificateVerifyer:可以将ICertificateVerifyer实现设置为此属性。之后创建的所有新请求将在使用安全协议且请求的UseAlternateSSL为true时使用此验证程序。 ICertificateVerifyer实现可用于实现服务器证书验证。 14):UseAlternateSSLDefaultValue:可以通过此属性更改HTTPRequest的UseAlternateSSL的默认值。 15):HTTPManager.MaxConnectionPerServer = 10; HTTPManager.RequestTimeout = TimeSpan.FromSeconds(120);
关于线程
- 1:因为插件内部使用线程并行处理所有请求,所以所有共享资源(缓存,cookie等)都是在设计和实现线程安全时考虑的。
 - 2:调用请求的回调函数和所有其他回调(如WebSocket的回调)都是在Unity的主线程上回调(如Unity的事件:awake, start, update, etc),因此您不必进行任何线程同步。
 - 3:在多个线程上创建,发送请求也是安全的,但是你应该调用BestHTTP.HTTPManager.Setup();在从Unity的一个事件(例如,awake,start)发送任何请求之前发挥作用。
 
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1487842110@qq.com
Title:BestHttp介绍1
文章字数:4.7k
Author:诸子百家-谁的天下?
Created At:2020-05-11, 11:41:32
Updated At:2021-03-28, 02:59:27
Url:http://yoursite.com/2020/05/11/Unity/BestHttp/BestHttp%E4%BB%8B%E7%BB%8D/Copyright: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。