Unity发送HTTPS请求
本文主要介绍2中发送HTTPS方法,其中第二种方法支持代理模式。代理模式可以有效节省DNS时间
对于延迟要求敏感的应用可以采用
一、常规HTTPS请求
直接使用发送HTTP请求一样的方法,参见Unity发送HTTP请求和文件下载
二、使用SslStream
模拟HTTPS请求,代码如下:
/// <summary>
/// 发送HTTPS请求
/// </summary>
/// <returns>The SSLP roxy request.</returns>
/// <param name="url">URL.</param>
/// <param name="proxyIp">Proxy ip.</param>
/// <param name="method">Method.</param>
/// <param name="paramsMap">Parameters map.</param>
/// <param name="timeout">Timeout.</param>
public static string SendSSLProxyRequest(string url, string proxyIp, string method = "GET", Dictionary<string, string> paramsMap = null, int timeout = 2000)
{
if (method == "GET")
{
url = BuildURL(url, paramsMap);
}
Uri uri = new Uri(url);
TcpClient client = null;
SslStream sslStream = null;
try
{
// Connect socket
client = new TcpClient(proxyIp, 443);
// Wrap in SSL stream
sslStream = new SslStream(client.GetStream(), false, certificateValidationCallback, null);
sslStream.ReadTimeout = timeout;
sslStream.WriteTimeout = timeout;
// 进行校验
sslStream.AuthenticateAsClient(uri.Host);
// Send request
string sendData = @"{0} {1} HTTP/1.1
Host: {2}
";
sendData = string.Format(sendData, method, uri.AbsoluteUri, uri.Host);
// 检查POST内容
int length = -1;
if ("POST".Equals(method) && null != paramsMap)
{
StringBuilder postBuilder = new StringBuilder();
foreach (var pair in paramsMap)
{
if (postBuilder.Length > 0)
{
postBuilder.Append("&");
}
postBuilder.Append(pair.Key).Append("=").Append(pair.Value);
}
length = Encoding.UTF8.GetBytes(postBuilder.ToString()).Length;
sendData += string.Format(@"Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: {0}
{1}", length, postBuilder.ToString());
}
else
{
sendData += "\r\n";
}
// 发送数据
byte[] bytes = Encoding.UTF8.GetBytes(sendData);
sslStream.Write(bytes, 0, bytes.Length);
sslStream.Flush();
// 读取数据
byte[] buffer = new byte[2048];
length = -1;
int contentLength = -1;
int dataLen = -1;
int statusCode = -1;
string statusMsg = null;
StringBuilder responseBuilder = new StringBuilder();
do
{
length = sslStream.Read(buffer, 0, buffer.Length);
if (length <= 0) {
break;
}
string content = Encoding.UTF8.GetString(buffer, 0, length);
responseBuilder.Append(content);
if (contentLength == -1)
{
int contentIndex = content.IndexOf("\r\n\r\n");
if (contentIndex > 0)
{
content = responseBuilder.ToString();
// 获取响应代码
string statusString = content.Substring(0, content.IndexOf("\r\n"));
string[] statusArray = statusString.Split(' ');
statusCode = Convert.ToInt32(statusArray[1]);
statusMsg = statusArray[2];
// 获取内容长度
int start = content.IndexOf("Content-Length:");
int end = content.IndexOf("\r\n", start);
contentLength = Convert.ToInt32(content.Substring(start + 16, end - start - 16));
content = content.Substring(contentIndex + 4);
responseBuilder.Length = 0;
responseBuilder.Append(content);
dataLen = Encoding.UTF8.GetBytes(content).Length;
}
}
else
{
dataLen += length;
}
if (dataLen >= contentLength)
{
break;
}
} while (length != 0);
if (statusCode == 200) {
return responseBuilder.ToString();
} else {
Log.Instance.errorFormat("send request error, url:{0}, responseCode:{1}, error:{2}", url, statusCode, statusMsg);
}
}
catch (Exception e)
{
Log.Instance.errorFormat("send request error, url:{0}", e, url);
}
finally
{
if (null != sslStream)
{
sslStream.Close();
}
if (null != client)
{
client.Close();
}
}
return null;
}
/// <summary>
/// 构建GET URL
/// </summary>
/// <returns>The UR.</returns>
/// <param name="url">URL.</param>
/// <param name="paramsMap">Parameters map.</param>
private static string BuildURL(string url, Dictionary<string, string> paramsMap)
{
if (null == paramsMap)
{
return url;
}
StringBuilder builder = new StringBuilder();
foreach (var pair in paramsMap)
{
if (builder.Length > 0)
{
builder.Append("&");
}
builder.Append(pair.Key).Append("=").Append(UrlEncode(pair.Value));
}
if (url.IndexOf("?") != -1)
{
url = url + "&" + builder.ToString();
}
else
{
url = url + "?" + builder.ToString();
}
return url;
}