using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Threading;
using LitJson;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using UnityEngine;
public delegate void OnHttpWebRequestCallback(string Jsondata, object userData);
public class HttpManager :MonoBehaviour
{
protected static List<Thread> mHttpThreadList = new List<Thread>();
protected static ThreadLock ThreadListLock = new ThreadLock ();
private static bool NoUpdate = true;
private static List<ObjectCallBack> UpdateQueue = new List<ObjectCallBack>();
private static List<ObjectCallBack> UpdateRunQueue = new List<ObjectCallBack>();
public static void ExecuteUpdate(ObjectCallBack action)
{
lock (UpdateQueue)
{
UpdateQueue.Add(action);
NoUpdate = false;
}
}
public static void Init()
{
GameObject gameObj = new GameObject("HttpManager");
gameObj.AddComponent<HttpManager>();
DontDestroyOnLoad(gameObj);
}
private void Update()
{
lock (UpdateQueue)
{
if (NoUpdate) return;
UpdateRunQueue.AddRange(UpdateQueue);
UpdateQueue.Clear();
NoUpdate = true;
for (var i = 0; i < UpdateRunQueue.Count; i++)
{
var action = UpdateRunQueue[i];
if (action == null) continue;
action.mCallBack(action.mJsonData,action.mUserData);
}
UpdateRunQueue.Clear();
}
}
public void Destroy()
{
ThreadListLock.waitForUnlock();
int count = mHttpThreadList.Count;
for(int i = 0; i < count; ++i)
{
mHttpThreadList[i].Abort();
mHttpThreadList[i] = null;
}
mHttpThreadList.Clear();
mHttpThreadList = null;
ThreadListLock.unlock();
}
public static byte[] DownloadFile(string url)
{
Debug.Log("开始http下载:" + url);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
WebResponse response = request.GetResponse();
Stream inStream = response.GetResponseStream();
MemoryStream downloadStream = new MemoryStream();
byte[] tempBytes = new byte[1024];
int readCount = 0;
do
{
readCount = inStream.Read(tempBytes, 0, tempBytes.Length);
downloadStream.Write(tempBytes, 0, readCount);
} while (readCount > 0);
byte[] dataBytes = downloadStream.ToArray();
downloadStream.Close();
inStream.Close();
response.Close();
Debug.Log("http下载完成:" + url);
return dataBytes;
}
public static JsonData HttpWebRequestPostFile(string url, List<FormItem> itemList, OnHttpWebRequestCallback callback, object callbakcUserData, bool logError)
{
string boundary = "----" + DateTime.Now.Ticks.ToString("x");
string fileFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + "\r\nContent-Type: application/octet-stream" + "\r\n\r\n";
string dataFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"" + "\r\n\r\n{1}";
MemoryStream postStream = new MemoryStream();
foreach (var item in itemList)
{
string formdata = null;
if (item.mFileContent != null)
{
formdata = string.Format(fileFormdataTemplate, "fileContent", item.mFileName);
}
else
{
formdata = string.Format(dataFormdataTemplate, item.mKey, item.mValue);
}
byte[] formdataBytes = null;
if (postStream.Length == 0)
{
formdataBytes = StringToBytes(formdata.Substring(2, formdata.Length - 2), Encoding.UTF8);
}
else
{
formdataBytes = StringToBytes(formdata, Encoding.UTF8);
}
postStream.Write(formdataBytes, 0, formdataBytes.Length);
if (item.mFileContent != null && item.mFileContent.Length > 0)
{
postStream.Write(item.mFileContent, 0, item.mFileContent.Length);
}
}
var footer = StringToBytes("\r\n--" + boundary + "--\r\n", Encoding.UTF8);
postStream.Write(footer, 0, footer.Length);
byte[] postBytes = postStream.ToArray();
ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(url));
webRequest.Method = "POST";
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
webRequest.Timeout = 10000;
webRequest.Credentials = CredentialCache.DefaultCredentials;
webRequest.ContentLength = postBytes.Length;
if (callback != null)
{
RequestThreadParam threadParam = new RequestThreadParam();
threadParam.mRequest = webRequest;
threadParam.mByteArray = postBytes;
threadParam.mCallback = callback;
threadParam.mUserData = callbakcUserData;
threadParam.mFullURL = url;
threadParam.mLogError = logError;
Thread httpThread = new Thread(WaitPostHttpWebRequest);
threadParam.mThread = httpThread;
httpThread.Start(threadParam);
httpThread.IsBackground = true;
ThreadListLock.waitForUnlock();
mHttpThreadList.Add(httpThread);
ThreadListLock.unlock();
return null;
}
else
{
try
{
Stream newStream = webRequest.GetRequestStream();
newStream.Write(postBytes, 0, postBytes.Length);
newStream.Close();
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
StreamReader php = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string phpend = php.ReadToEnd();
php.Close();
response.Close();
return JsonMapper.ToObject(phpend);
}
catch (Exception)
{
return null;
}
}
}
public static JsonData HttpWebRequestPost(string url, byte[] data, string contentType, OnHttpWebRequestCallback callback, object callbakcUserData, bool logError)
{
ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(url));
webRequest.Method = "POST";
webRequest.ContentType = contentType;
webRequest.ContentLength = data.Length;
webRequest.Credentials = CredentialCache.DefaultCredentials;
webRequest.Timeout = 10000;
if (callback != null)
{
RequestThreadParam threadParam = new RequestThreadParam();
threadParam.mRequest = webRequest;
threadParam.mByteArray = data;
threadParam.mCallback = callback;
threadParam.mUserData = callbakcUserData;
threadParam.mFullURL = url;
threadParam.mLogError = logError;
Thread httpThread = new Thread(WaitPostHttpWebRequest);
threadParam.mThread = httpThread;
httpThread.Start(threadParam);
httpThread.IsBackground = true;
ThreadListLock.waitForUnlock();
mHttpThreadList.Add(httpThread);
ThreadListLock.unlock();
return null;
}
else
{
try
{
Stream newStream = webRequest.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
StreamReader streamreader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string value = streamreader.ReadToEnd();
streamreader.Close();
response.Close();
return value;
}
catch (Exception)
{
return null;
}
}
}
public static JsonData httpWebRequestPost(string url, byte[] data, OnHttpWebRequestCallback callback = null, object callbakcUserData = null, bool logError = true)
{
return HttpWebRequestPost(url, data, "application/x-www-form-urlencoded", callback, callbakcUserData, logError);
}
public static JsonData httpWebRequestPost(string url, string param, OnHttpWebRequestCallback callback = null, object callbakcUserData = null, bool logError = true)
{
return HttpWebRequestPost(url, StringToBytes(param, Encoding.UTF8), "application/x-www-form-urlencoded", callback, callbakcUserData, logError);
}
public static JsonData httpWebRequestPost(string url, string param, string contentType, OnHttpWebRequestCallback callback = null, object callbakcUserData = null, bool logError = true)
{
return HttpWebRequestPost(url, StringToBytes(param, Encoding.UTF8), contentType, callback, callbakcUserData, logError);
}
static public string generateHttpGet(string url, Dictionary<string, string> get)
{
string Parameters = "";
if (get.Count > 0)
{
Parameters = "?";
foreach (KeyValuePair<string, string> post_arg in get)
{
Parameters += post_arg.Key + "=" + post_arg.Value + "&";
}
removeLast(ref Parameters, '&');
}
return url + Parameters;
}
public static void removeLast(ref string stream, char key)
{
int lastCommaPos = stream.LastIndexOf(key);
if (lastCommaPos != -1)
{
stream = stream.Remove(lastCommaPos, 1);
}
}
public static JsonData HttpWebRequestGet(string urlString, OnHttpWebRequestCallback callback = null, bool logError = true)
{
HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(new Uri(urlString));
httprequest.Method = "GET";
httprequest.KeepAlive = false;
httprequest.ProtocolVersion = HttpVersion.Version11;
httprequest.ContentType = "application/x-www-form-urlencoded";
httprequest.AllowAutoRedirect = true;
httprequest.MaximumAutomaticRedirections = 2;
httprequest.Timeout = 10000;
if (callback != null)
{
RequestThreadParam threadParam = new RequestThreadParam();
threadParam.mRequest = httprequest;
threadParam.mByteArray = null;
threadParam.mCallback = callback;
threadParam.mFullURL = urlString;
threadParam.mLogError = logError;
Thread httpThread = new Thread(waitGetHttpWebRequest);
threadParam.mThread = httpThread;
httpThread.Start(threadParam);
httpThread.IsBackground = true;
ThreadListLock.waitForUnlock();
mHttpThreadList.Add(httpThread);
ThreadListLock.unlock();
return null;
}
else
{
try
{
HttpWebResponse response = (HttpWebResponse)httprequest.GetResponse();
Stream steam = response.GetResponseStream();
StreamReader reader = new StreamReader(steam, Encoding.UTF8);
string pageStr = reader.ReadToEnd();
reader.Close();
response.Close();
httprequest.Abort();
reader = null;
response = null;
httprequest = null;
return JsonMapper.ToObject(pageStr);
}
catch (Exception)
{
return null;
}
}
}
static protected void WaitPostHttpWebRequest(object param)
{
RequestThreadParam threadParam = param as RequestThreadParam;
ObjectCallBack callback = new ObjectCallBack();
callback.mCallBack = threadParam.mCallback;
try
{
Stream newStream = threadParam.mRequest.GetRequestStream();
newStream.Write(threadParam.mByteArray, 0, threadParam.mByteArray.Length);
newStream.Close();
HttpWebResponse response = (HttpWebResponse)threadParam.mRequest.GetResponse();
StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string phpend = streamReader.ReadToEnd();
streamReader.Close();
response.Close();
streamReader = null;
response = null;
callback.mJsonData = phpend;
callback.mUserData = threadParam.mUserData;
}
catch (Exception e)
{
callback.mJsonData = String.Empty;
callback.mUserData = null;
string info = "http post result exception:" + e.Message + ", url:" + threadParam.mFullURL;
Debug.Log(info);
}
finally
{
ExecuteUpdate(callback);
threadParam.mRequest.Abort();
threadParam.mRequest = null;
ThreadListLock.waitForUnlock();
if(mHttpThreadList != null)
{
mHttpThreadList.Remove(threadParam.mThread);
}
ThreadListLock.unlock();
}
}
static protected void waitGetHttpWebRequest(object param)
{
RequestThreadParam threadParam = param as RequestThreadParam;
ObjectCallBack callback = new ObjectCallBack();
callback.mCallBack = threadParam.mCallback;
try
{
HttpWebResponse response = (HttpWebResponse)threadParam.mRequest.GetResponse();
Stream steam = response.GetResponseStream();
StreamReader reader = new StreamReader(steam, Encoding.UTF8);
string pageStr = reader.ReadToEnd();
reader.Close();
response.Close();
reader = null;
response = null;
callback.mJsonData = pageStr;
callback.mUserData = threadParam.mUserData;
}
catch (Exception e)
{
callback.mJsonData = "";
callback.mUserData = null;
string info = "http get result exception : " + e.Message + ", url : " + threadParam.mFullURL;
Debug.Log(info);
}
finally
{
threadParam.mRequest.Abort();
threadParam.mRequest = null;
ExecuteUpdate(callback);
ThreadListLock.waitForUnlock();
if(mHttpThreadList != null)
{
mHttpThreadList.Remove(threadParam.mThread);
}
ThreadListLock.unlock();
}
}
protected static bool MyRemoteCertificateValidationCallback(System.Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
bool isOk = true;
if (sslPolicyErrors != SslPolicyErrors.None)
{
for (int i = 0; i < chain.ChainStatus.Length; i++)
{
if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown)
{
continue;
}
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
bool chainIsValid = chain.Build((X509Certificate2)certificate);
if (!chainIsValid)
{
isOk = false;
break;
}
}
}
return isOk;
}
public static byte[] StringToBytes(string str, Encoding encoding)
{
return encoding.GetBytes(str);
}
}
public class RequestThreadParam
{
public HttpWebRequest mRequest;
public byte[] mByteArray;
public OnHttpWebRequestCallback mCallback;
public object mUserData;
public Thread mThread;
public string mFullURL;
public bool mLogError;
}
public class FormItem
{
public byte[] mFileContent;
public string mFileName;
public string mKey;
public string mValue;
public FormItem(byte[] file, string fileName)
{
mFileContent = file;
mFileName = fileName;
}
public FormItem(string key, string value)
{
mKey = key;
mValue = value;
}
}
public class ObjectCallBack
{
public OnHttpWebRequestCallback mCallBack;
public string mJsonData;
public object mUserData;
}