Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/100.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Unity iOS上发出HTTP请求的方法?_C#_Ios_Multithreading_Http_Unity3d - Fatal编程技术网

C# 在Unity iOS上发出HTTP请求的方法?

C# 在Unity iOS上发出HTTP请求的方法?,c#,ios,multithreading,http,unity3d,C#,Ios,Multithreading,Http,Unity3d,我需要使用所有标准RESTful方法发送HTTP请求,并访问请求主体,以便使用它发送/接收JSON。我已经调查过了 WebRequest.HttpWebRequest 这几乎可以完美地工作,但在某些情况下,例如,如果服务器停机,函数GetResponse可能需要几秒钟才能返回—因为它是一种同步方法—在这段时间内冻结应用程序。此方法的异步版本BeginGetResponse似乎不能异步工作(无论如何,在Unity中),因为它仍然在该时间段内冻结应用程序 UnityEngine.WWW# 出于某种原

我需要使用所有标准RESTful方法发送HTTP请求,并访问请求主体,以便使用它发送/接收JSON。我已经调查过了

WebRequest.HttpWebRequest 这几乎可以完美地工作,但在某些情况下,例如,如果服务器停机,函数GetResponse可能需要几秒钟才能返回—因为它是一种同步方法—在这段时间内冻结应用程序。此方法的异步版本BeginGetResponse似乎不能异步工作(无论如何,在Unity中),因为它仍然在该时间段内冻结应用程序

UnityEngine.WWW# 出于某种原因,我只支持POST和GET请求,但我还需要PUT和DELETE(标准RESTful方法),所以我不必再进一步研究它了

系统线程 为了在不冻结应用程序的情况下运行WebRequest.HttpWebRequest.GetResponse,我研究了使用线程。线程似乎在编辑器中工作(但似乎非常不稳定-如果在应用程序退出时不停止线程,即使在停止线程时,它也会在编辑器中永远运行),并且在构建到iOS设备时,在我尝试启动线程时,线程会立即崩溃(我忘了写错误,现在无法访问它)

在本机iOS应用程序中运行线程,并与Unity应用程序建立桥接 可笑的是,我甚至都不打算这样做

UniWeb 这个。我想知道他们是怎么做到的

下面是我正在尝试的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);
    }
}

。。。基于此:

我让线程在iOS上工作-我相信它是由于幽灵线程或其他原因而崩溃的。重新启动设备似乎已经修复了崩溃问题,因此我将只使用WebRequest.HttpWebRequest和线程。

好的,我终于写了。我们基本上需要一个请求状态、一个回调方法和一个超时线程。在这里,我只是复制(现在称为unity3d wiki)。这是过时的代码,但比现有代码小,因此在这里显示更方便。现在我已经删除了(在unit3d wiki中)
System.Action
static
以提高性能和简化性:

用法
静态公共类实例;
无效唤醒(){
Instance=GetComponent();
}
静态私有IEnumerator CheckAvailabilityNow(){
布尔·福努尔;
字符串checkThisURL=”http://www.example.com/index.html";
yield return Instance.start例程(
WebAsync.CheckForMissingURL(checkThisURL,value=>foundURL=!value)
);
Log(“是否存在”+checkThisURL+“是否存在?”+foundURL);
}
WebAsync.cs
使用系统;
使用System.IO;
Net系统;
使用系统线程;
使用系统集合;
使用UnityEngine;
/// 
///RequestState类通过异步调用传递数据。
/// 
公共类请求状态
{
公共WebRequest-WebRequest;
公共字符串错误消息;
公共请求状态()
{
webRequest=null;
errorMessage=null;
}
}
公共类WebAsync{
const int TIMEOUT=10;//秒
/// 
///如果URL返回404或者连接断开,那么它就丢失了。否则,我们认为它没问题。
/// 
/// 
///完全格式化的URL。
/// 
/// 
///如果404或连接断开,这将为'true',对于其他所有内容,这将为'false'。
///按此使用,其中“值”是一个系统:
///value=>您的bool var=value
/// 
静态公共IEnumerator CheckForMissingURL(字符串url,System.Action结果){
结果(假);
Uri httpSite=新Uri(url);
WebRequest WebRequest=WebRequest.Create(httpSite);
//我们只需要HTTP的头
webRequest.Method=“HEAD”;
RequestState RequestState=新的RequestState();
//将请求放入状态对象中,以便可以传递
requestState.webRequest=webRequest;
//在这里执行实际的异步调用
IAsyncResult asyncResult=(IAsyncResult)webRequest.BeginGetResponse(
新的异步回调(RespCallback),requestState);
//WebRequestTimeout在异步调用中不起作用,所以我们需要它
ThreadPool.RegisterWaitForSingleObject(
asyncResult.AsyncWaitHandle,
新WaitOrTimerCallback(ScanTimeoutCallback),
请求国,
(超时*1000),//显然是因为这是以毫秒为单位的
真的
);
//等待通话结束
而(!asyncResult.IsCompleted){yield return null;}
//处理结果
if(requestState.errorMessage!=null){
if(requestState.errorMessage.Contains(“404”)| | requestState.errorMessage.Contains(“NameResolutionFailure”)){
结果(真);
}否则{
Debug.LogWarning(“[WebAsync]尝试验证URL'+URL+'是否存在时出错:”+requestState.errorMessage);
}
}
}
静态私有void RespCallback(IAsyncResult asyncResult){
RequestState RequestState=(RequestState)asyncResult.AsyncState;
WebRequest WebRequest=requestState.WebRequest;
试一试{
EndGetResponse(异步结果);
}捕获(WebException WebException){
requestState.errorMessage=webException.Message;
}
}
静态私有void ScanTimeoutCallback(对象状态,bool timedOut){
if(timedOut){
RequestState RequestState=(RequestState)状态;
if(requestState!=null)
requestState.webRequest.Abort();
}否则{
RegisteredWaitHandle RegisteredWaitHandle=(RegisteredWaitHandle)状态;
if(registeredWaitHandle!=null)
registeredWaitHandle.Unregister(null);
}
}
}
或者,为了安全起见,您可以通过预先编写的自定义标题的AJAX函数发送它 用这个你可以
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);
        }
    }
}
// javascript in the web player not ios, android or desktop you could just run the following code:

var jscall:String;
    jscall="var reqScript = document.createElement('script');";
    jscall+="reqScript.src = 'synchmanager_secure2.jsp?userid="+uid+"&token="+access_token+"&rnd='+Math.random()*777;";
    jscall+="document.body.appendChild(reqScript);";
Application.ExternalEval(jscall);
// cs
string jscall;
    jscall="var reqScript = document.createElement('script');";
    jscall+="reqScript.src = 'synchmanager_secure2.jsp?userid="+uid+"&token="+access_token+"&rnd='+Math.random()*777;";
    jscall+="document.body.appendChild(reqScript);";
    Application.ExternalEval(jscall);

// then update your object using the your return in a function like this
// json return object always asynch
function sendMyReturn(args){
     var unity=getUnity();
     unity.SendMessage("object", "function", args );
}
sendMyReturn(args);