JSONを送受信するには、すべての標準RESTfulメソッドを使用してHTTPリクエストを送信し、リクエストの本文にアクセスする必要があります。私は調べました、
これはほぼ完全に機能しますが、たとえば、サーバーがダウンしている場合、関数GetResponseは、同期メソッドであるため、アプリケーションがその期間フリーズするため、数秒かかる場合があります。このメソッドの非同期バージョンであるBeginGetResponseは、アプリケーションがその期間フリーズしているため、(とにかくUnityで)非同期に動作していないようです。
何らかの理由でPOSTおよびGETリクエストのみをサポートしますが、PUTおよびDELETE(標準RESTfulメソッド)も必要とするため、これ以上検討する必要はありませんでした。
アプリケーションをフリーズせずにWebRequest.HttpWebRequest.GetResponseを実行するために、スレッドを使用して調べました。スレッドはエディターで動作しているように見えます(ただし、非常に揮発性のように見えます。アプリケーションの終了時にスレッドを停止しないと、スレッドを停止してもエディターで永久に実行され続けます)。iOSデバイスにビルドすると、すぐにクラッシュしますスレッドを開始しようとしたとき(エラーを書き留めるのを忘れて、今はアクセスできません)。
ばかげて、これを試みるつもりもありません。
この。彼らがそれをどのように管理したか知りたいのですが。
これが私が試しているWebRequest.BeginGetResponseメソッドの例です、
// The RequestState class passes data across async calls.
public class RequestState
{
const int BufferSize = 1024;
public StringBuilder RequestData;
public byte[] BufferRead;
public WebRequest Request;
public Stream ResponseStream;
// Create Decoder for appropriate enconding type.
public Decoder StreamDecode = Encoding.UTF8.GetDecoder();
public RequestState()
{
BufferRead = new byte[BufferSize];
RequestData = new StringBuilder(String.Empty);
Request = null;
ResponseStream = null;
}
}
public class WebRequester
{
private void ExecuteRequest()
{
RequestState requestState = new RequestState();
WebRequest request = WebRequest.Create("mysite");
request.BeginGetResponse(new AsyncCallback(Callback), requestState);
}
private void Callback(IAsyncResult ar)
{
// Get the RequestState object from the async result.
RequestState rs = (RequestState) ar.AsyncState;
// Get the WebRequest from RequestState.
WebRequest req = rs.Request;
// Call EndGetResponse, which produces the WebResponse object
// that came from the request issued above.
WebResponse resp = req.EndGetResponse(ar);
}
}
...これに基づいて: http://msdn.Microsoft.com/en-us/library/86wf6409(v = vs.71).aspx
私はiOSで動作するようにスレッド化しました-ゴーストスレッドなどが原因でクラッシュしたと思います。デバイスを再起動するとクラッシュが修正されたようなので、スレッドでWebRequest.HttpWebRequestを使用します。
さて、ようやく 自分の解決策 を書くことができました。基本的にはRequestState、aCallback Method、およびTimeOut Thread。ここでは whatwasdone in UnifyCommunity (現在はunity3d wikiと呼ばれています)をコピーします。これは古いコードですが、そこにあるものよりも小さいので、ここに何かを表示する方が便利です。今、私は(unit3d wikiで)削除しましたSystem.Action
およびstatic
は、パフォーマンスとシンプルさを実現します。
static public ThisClass Instance;
void Awake () {
Instance = GetComponent<ThisClass>();
}
static private IEnumerator CheckAvailabilityNow () {
bool foundURL;
string checkThisURL = "http://www.example.com/index.html";
yield return Instance.StartCoroutine(
WebAsync.CheckForMissingURL(checkThisURL, value => foundURL = !value)
);
Debug.Log("Does "+ checkThisURL +" exist? "+ foundURL);
}
using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Collections;
using UnityEngine;
/// <summary>
/// The RequestState class passes data across async calls.
/// </summary>
public class RequestState
{
public WebRequest webRequest;
public string errorMessage;
public RequestState ()
{
webRequest = null;
errorMessage = null;
}
}
public class WebAsync {
const int TIMEOUT = 10; // seconds
/// <summary>
/// If the URLs returns 404 or connection is broken, it's missing. Else, we suppose it's fine.
/// </summary>
/// <param name='url'>
/// A fully formated URL.
/// </param>
/// <param name='result'>
/// This will bring 'true' if 404 or connection broken and 'false' for everything else.
/// Use it as this, where "value" is a System sintaxe:
/// value => your-bool-var = value
/// </param>
static public IEnumerator CheckForMissingURL (string url, System.Action<bool> result) {
result(false);
Uri httpSite = new Uri(url);
WebRequest webRequest = WebRequest.Create(httpSite);
// We need no more than HTTP's head
webRequest.Method = "HEAD";
RequestState requestState = new RequestState();
// Put the request into the state object so it can be passed around
requestState.webRequest = webRequest;
// Do the actual async call here
IAsyncResult asyncResult = (IAsyncResult) webRequest.BeginGetResponse(
new AsyncCallback(RespCallback), requestState);
// WebRequest timeout won't work in async calls, so we need this instead
ThreadPool.RegisterWaitForSingleObject(
asyncResult.AsyncWaitHandle,
new WaitOrTimerCallback(ScanTimeoutCallback),
requestState,
(TIMEOUT *1000), // obviously because this is in miliseconds
true
);
// Wait until the the call is completed
while (!asyncResult.IsCompleted) { yield return null; }
// Deal up with the results
if (requestState.errorMessage != null) {
if ( requestState.errorMessage.Contains("404") || requestState.errorMessage.Contains("NameResolutionFailure") ) {
result(true);
} else {
Debug.LogWarning("[WebAsync] Error trying to verify if URL '"+ url +"' exists: "+ requestState.errorMessage);
}
}
}
static private void RespCallback (IAsyncResult asyncResult) {
RequestState requestState = (RequestState) asyncResult.AsyncState;
WebRequest webRequest = requestState.webRequest;
try {
webRequest.EndGetResponse(asyncResult);
} catch (WebException webException) {
requestState.errorMessage = webException.Message;
}
}
static private void ScanTimeoutCallback (object state, bool timedOut) {
if (timedOut) {
RequestState requestState = (RequestState)state;
if (requestState != null)
requestState.webRequest.Abort();
} else {
RegisteredWaitHandle registeredWaitHandle = (RegisteredWaitHandle)state;
if (registeredWaitHandle != null)
registeredWaitHandle.Unregister(null);
}
}
}