using System.Collections.Generic; using System; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; public static class AxiHttp { public const char T = '\n'; public const string CT = "\r\n"; public const string CTRL = "\r\n\r\n"; public const string Content_Length_Str = "content-length: "; public const string Content_Length_Str_M = "Content-Length: "; public const string Content_Length = "content-length"; public const string Content_Encoding = "content-encoding"; public const string Transfer_Encoding = "transfer-encoding"; public const string Connection = "connection"; public static long index = 0; static int singlePkgMaxRead = 1024; public class WaitAxiRequest : UnityEngine.CustomYieldInstruction { public AxiRespInfo mReqAsync; public WaitAxiRequest(AxiRespInfo reqAsync) { mReqAsync = reqAsync; } ~WaitAxiRequest() { mReqAsync = null; } public override bool keepWaiting { get { return !mReqAsync.isDone; } } } public static void Log(string log) { UnityEngine.Debug.Log(log); //Console.WriteLine(log); } static Dictionary dictIP2Address = new Dictionary(); public class AxiRespInfo { public bool isDone = false; public AxiDownLoadMode downloadMode = AxiDownLoadMode.NotDownLoad; public string Err = null; public string host = "";//host主机头 public string url = "";//pathAndQuery public int port = 80; public string requestRaw = ""; public string encoding = ""; public string header = ""; public string text { get { return body; } } public string body = ""; public string reuqestBody = ""; public string reuqestHeader = ""; public Dictionary headers = new Dictionary(); public string response = ""; //public string gzip = ""; public bool isGzip = false; public int length = 0; public int code = 0; public int location = 0; public int runTime = 0;//获取网页消耗时间,毫秒 public int sleepTime = 0;//休息时间 public string cookies = ""; public bool bTimeOut = false; public int NeedloadedLenght; public int loadedLenght; public byte[] data { get { return bodyRaw; } } public byte[] bodyRaw; public string fileName; public float DownLoadPr => NeedloadedLenght <= 0 ? -1 : (float)loadedLenght / NeedloadedLenght; public BinaryWriter binaryWriter; } public static IPAddress GetDnsIP(string str) { if (!dictIP2Address.ContainsKey(str)) { try { IPAddress ip = Dns.GetHostEntry(str).AddressList[0]; dictIP2Address[str] = ip; } catch { return null; } } return dictIP2Address[str]; } public enum AxiDownLoadMode { NotDownLoad = 0, DownLoadBytes = 1, DownloadToBinaryWriter = 2 } public static AxiRespInfo AxiRequest(string url) { AxiRespInfo respInfo = new AxiRespInfo(); respInfo.downloadMode = AxiDownLoadMode.NotDownLoad; SendAxiRequest(url, ref respInfo); return respInfo; } public static WaitAxiRequest AxiRequestAsync(string url) { AxiRespInfo respInfo = new AxiRespInfo(); respInfo.downloadMode = AxiDownLoadMode.NotDownLoad; WaitAxiRequest respAsync = new WaitAxiRequest(respInfo); Task task = new Task(() => SendAxiRequest(url, ref respInfo)); task.Start(); return respAsync; } public static AxiRespInfo AxiDownload(string url) { AxiRespInfo respInfo = new AxiRespInfo(); respInfo.downloadMode = AxiDownLoadMode.DownLoadBytes; SendAxiRequest(url, ref respInfo); return respInfo; } public static AxiRespInfo AxiDownloadAsync(string url) { AxiRespInfo respInfo = new AxiRespInfo(); respInfo.downloadMode = AxiDownLoadMode.DownLoadBytes; Task task = new Task(() => SendAxiRequest(url, ref respInfo)); task.Start(); return respInfo; } static void SendAxiRequest(string url, ref AxiRespInfo respinfo,int timeout = 1000 * 1000, string encoding = "UTF-8") { if (url.ToLower().StartsWith("https://")) SendAxiRequestHttps(url, ref respinfo,timeout, encoding);// SendAxiRequestHttps(url, ref respinfo, timeout, encoding); else SendAxiRequestHttp(url, ref respinfo,timeout, encoding); } static void SendAxiRequestHttp(string url, ref AxiRespInfo respinfo, int timeout, string encoding) { Log("SendAxiRequestHttp"); respinfo.url = url; Stopwatch sw = new Stopwatch(); sw.Start(); respinfo.loadedLenght = 0; try { string strURI = url; string strHost = ""; string strIP = ""; int port = 0; string strRelativePath = ""; bool bSSL = false; bool foward_302 = true; if (!ParseURI(strURI, ref bSSL, ref strHost, ref strIP, ref port, ref strRelativePath)) { Log("ParseURI False"); respinfo.Err = "ParseURI False"; respinfo.code = 0; respinfo.isDone = true; return; } var ip = GetDnsIP(strHost); var ipEndPoint = new IPEndPoint(ip, port); using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) using (MemoryStream memoryStream = new MemoryStream()) { client.Connect(ipEndPoint); if (!client.Connected) { client.Close(); sw.Stop(); respinfo.code = 0; respinfo.isDone = true; return; } //string requestRaw = $"GET {strRelativePath} HTTP/1.1\r\nHost: {strHost}\r\nConnection: Close\r\n\r\n"; string request = $"GET {strURI} HTTP/1.1\r\nHost: {strHost}\r\nConnection: Close\r\n\r\n"; checkContentLength(ref respinfo, ref request); respinfo.requestRaw = request; byte[] temp_responseBody = new byte[singlePkgMaxRead]; byte[] buffer = Encoding.ASCII.GetBytes(request); client.Send(buffer); string tmp = ""; int len = 0; StringBuilder sb = new StringBuilder(); do { byte[] responseHeader = new byte[1]; len = client.Receive(responseHeader, 1, SocketFlags.None); if (len == 1) { char c = (char)responseHeader[0]; sb.Append(c); if (c.Equals(T)) { tmp = String.Concat(sb[sb.Length - 4], sb[sb.Length - 3], sb[sb.Length - 2], c); } } } while (!tmp.Equals(CTRL) && sw.ElapsedMilliseconds < timeout ); respinfo.header = sb.ToString().Replace(CTRL, ""); string[] headers = Regex.Split(respinfo.header, CT); if (headers != null && headers.Length > 0) { //处理header doHeader(ref respinfo, ref headers); } //自动修正编码 if (!String.IsNullOrEmpty(respinfo.encoding)) { encoding = respinfo.encoding; } Encoding encod = Encoding.GetEncoding(encoding); //302 301跳转 if ((respinfo.code == 302 || respinfo.code == 301) && foward_302) { StringBuilder rsb = new StringBuilder(respinfo.requestRaw); int urlStart = respinfo.requestRaw.IndexOf(" ") + 1; int urlEnd = respinfo.requestRaw.IndexOf(" HTTP"); if (urlStart != -1 && urlEnd != -1) { url = respinfo.requestRaw.Substring(urlStart, urlEnd - urlStart); rsb.Remove(urlStart, url.Length); String location = respinfo.headers["location"]; if (!respinfo.headers["location"].StartsWith("/") && !respinfo.headers["location"].StartsWith("http")) { location = Tools.getCurrentPath(url) + location; } rsb.Insert(urlStart, location); //return sendHTTPRequest(count, host, port, payload, rsb.ToString(), timeout, encoding, false); client.Close(); sw.Stop(); SendAxiRequest(url, ref respinfo, timeout, encoding); return; } } //根据请求头解析 if (respinfo.headers.ContainsKey(Content_Length)) { Log("User Head"); int length = int.Parse(respinfo.headers[Content_Length]); respinfo.NeedloadedLenght = length; // while (respinfo.loadedLenght < length // && sw.ElapsedMilliseconds < timeout // ) //{ // int readsize = length - respinfo.loadedLenght; // len = client.Receive(temp_responseBody, respinfo.loadedLenght, readsize, SocketFlags.None); // if (len > 0) // { // respinfo.loadedLenght += len; // } //} while (respinfo.loadedLenght < length && sw.ElapsedMilliseconds < timeout ) { //len = client.Receive(temp_responseBody, respinfo.loadedLenght, readsize, SocketFlags.None); int readsize = length - respinfo.loadedLenght; readsize = Math.Min(readsize, singlePkgMaxRead); len = client.Receive(temp_responseBody, 0, readsize, SocketFlags.None); if (len > 0) { memoryStream.Write(temp_responseBody, 0, len); respinfo.loadedLenght += len; } } } //解析chunked传输 else if (respinfo.headers.ContainsKey(Transfer_Encoding)) { Log("User chunked"); //读取长度 int chunkedSize = 0; byte[] chunkedByte = new byte[1]; //读取总长度 respinfo.loadedLenght = 0; do { string ctmp = ""; do { len = client.Receive(chunkedByte, 1, SocketFlags.None); ctmp += Encoding.UTF8.GetString(chunkedByte); } while ((ctmp.IndexOf(CT) == -1) && (sw.ElapsedMilliseconds < timeout) ); chunkedSize = Tools.convertToIntBy16(ctmp.Replace(CT, "")); //chunked的结束0\r\n\r\n是结束标志,单个chunked块\r\n结束 if (ctmp.Equals(CT)) { continue; } if (chunkedSize == 0) { //结束了 break; } //int onechunkLen = 0; //while (onechunkLen < chunkedSize // && sw.ElapsedMilliseconds < timeout // ) //{ // len = client.Receive(responseBody, respinfo.loadedLenght, chunkedSize - onechunkLen, SocketFlags.None); // if (len > 0) // { // onechunkLen += len; // respinfo.loadedLenght += len; // } //} int onechunkLen = 0; while (onechunkLen < chunkedSize && sw.ElapsedMilliseconds < timeout ) { //len = client.Receive(responseBody, respinfo.loadedLenght, chunkedSize - onechunkLen, SocketFlags.None); int readsize = chunkedSize - onechunkLen; readsize = Math.Min(readsize, singlePkgMaxRead); len = client.Receive(temp_responseBody, 0, readsize, SocketFlags.None); if (len > 0) { memoryStream.Write(temp_responseBody, 0, len); onechunkLen += len; respinfo.loadedLenght += len; } } //判断 } while (sw.ElapsedMilliseconds < timeout); } //connection close方式或未知body长度 else { Log("connection close or Unknow bodylenght"); while (sw.ElapsedMilliseconds < timeout) { if (client.Poll(timeout, SelectMode.SelectRead)) { if (client.Available > 0) { //len = client.Receive(responseBody, respinfo.loadedLenght, (1024 * 200) - respinfo.loadedLenght, SocketFlags.None); int readsize = (1024 * 200) - respinfo.loadedLenght; readsize = Math.Min(readsize, singlePkgMaxRead); len = client.Receive(temp_responseBody, 0, readsize, SocketFlags.None); if (len > 0) { memoryStream.Write(temp_responseBody, 0, len); respinfo.loadedLenght += len; } } else { break; } } } } byte[] responseBody = memoryStream.ToArray(); //如果是下载 if (respinfo.downloadMode > AxiDownLoadMode.NotDownLoad) { //判断是否gzip if (respinfo.headers.ContainsKey(Content_Encoding)) { respinfo.bodyRaw = unGzipBytes(responseBody, respinfo.loadedLenght); } else { respinfo.bodyRaw = responseBody; } // 使用Uri类解析URL Uri uri = new Uri(url); respinfo.fileName = Path.GetFileName(uri.LocalPath); } else { //判断是否gzip if (respinfo.headers.ContainsKey(Content_Encoding)) { respinfo.body = unGzip(responseBody, respinfo.loadedLenght, encod); } else { respinfo.body = encod.GetString(responseBody, 0, respinfo.loadedLenght); } } client.Close(); } } catch (Exception ex) { respinfo.Err = $"ex : {ex.ToString()}"; } finally { sw.Stop(); respinfo.length = respinfo.loadedLenght; respinfo.runTime = (int)sw.ElapsedMilliseconds; respinfo.bTimeOut = sw.ElapsedMilliseconds >= timeout; //if (socket != null) //{ // clientSocket.Close(); //} respinfo.isDone = true; } } static void SendAxiRequestHttps(string url, ref AxiRespInfo respinfo, int timeout, string encoding) { respinfo.url = url; Stopwatch sw = new Stopwatch(); sw.Start(); respinfo.loadedLenght = 0; TcpClient client = null; try { string strURI = url; string strHost = ""; string strIP = ""; int port = 0; string strRelativePath = ""; bool bSSL = false; bool foward_302 = true; if (!ParseURI(strURI, ref bSSL, ref strHost, ref strIP, ref port, ref strRelativePath)) { Log("ParseURI False"); respinfo.Err = "ParseURI False"; respinfo.code = 0; respinfo.isDone = true; return; } //var ip = Dns.GetHostEntry(strHost).AddressList[0]; //var ipEndPoint = new IPEndPoint(ip, port); //using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) //using (TcpClient tcpclient = new TcpClient()) using (MemoryStream memoryStream = new MemoryStream()) { //client.Connect(ipEndPoint); TimeOutSocket tos = new TimeOutSocket(); client = tos.Connect(strHost, port, timeout); if (!client.Connected) { client.Close(); sw.Stop(); respinfo.code = 0; respinfo.isDone = true; return; } SslStream ssl = null; //string requestRaw = $"GET {strRelativePath} HTTP/1.1\r\nHost: {strHost}\r\nConnection: Close\r\n\r\n"; string request = $"GET {strURI} HTTP/1.1\r\nHost: {strHost}\r\nConnection: Close\r\n\r\n"; ssl = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate)); SslProtocols protocol = SslProtocols.Ssl3 | SslProtocols.Ssl2 | SslProtocols.Tls; ssl.AuthenticateAsClient(strHost, null, protocol, false); if (ssl.IsAuthenticated) { checkContentLength(ref respinfo, ref request); respinfo.requestRaw = request; byte[] requestByte = Encoding.UTF8.GetBytes(request); ssl.Write(requestByte); ssl.Flush(); } checkContentLength(ref respinfo, ref request); respinfo.requestRaw = request; byte[] temp_responseBody = new byte[singlePkgMaxRead]; //byte[] buffer = Encoding.ASCII.GetBytes(requestRaw); //client.Send(buffer); string tmp = ""; int len = 0; StringBuilder sb = new StringBuilder(); do { byte[] responseHeader = new byte[1]; int read = ssl.ReadByte(); char c = (char)read; sb.Append(c); if (c.Equals(T)) { tmp = String.Concat(sb[sb.Length - 4], sb[sb.Length - 3], sb[sb.Length - 2], c); } } while (!tmp.Equals(CTRL) && sw.ElapsedMilliseconds < timeout ); respinfo.header = sb.ToString().Replace(CTRL, ""); string[] headers = Regex.Split(respinfo.header, CT); if (headers != null && headers.Length > 0) { //处理header doHeader(ref respinfo, ref headers); } //自动修正编码 if (!String.IsNullOrEmpty(respinfo.encoding)) { encoding = respinfo.encoding; } Encoding encod = Encoding.GetEncoding(encoding); //302 301跳转 if ((respinfo.code == 302 || respinfo.code == 301) && foward_302) { int urlStart = respinfo.requestRaw.IndexOf(" "); int urlEnd = respinfo.requestRaw.IndexOf(" HTTP"); if (urlStart != -1 && urlEnd != -1) { url = respinfo.requestRaw.Substring(urlStart + 1, urlEnd - urlStart - 1); if (!respinfo.headers["location"].StartsWith("/") && !respinfo.headers["location"].StartsWith("https")) { respinfo.requestRaw = respinfo.requestRaw.Replace(url, Tools.getCurrentPath(url) + respinfo.headers["location"]); } else { respinfo.requestRaw = respinfo.requestRaw.Replace(url, respinfo.headers["location"]); } //return sendHTTPRequest(count, host, port, payload, rsb.ToString(), timeout, encoding, false); client.Close(); sw.Stop(); SendAxiRequest(url, ref respinfo, timeout, encoding); return; } } //根据请求头解析 if (respinfo.headers.ContainsKey(Content_Length)) { Log("Use Head"); int length = int.Parse(respinfo.headers[Content_Length]); respinfo.NeedloadedLenght = length; while (respinfo.loadedLenght < length && sw.ElapsedMilliseconds < timeout) { //len = ssl.Read(responseBody, respinfo.loadedLenght, length - respinfo.loadedLenght); int readsize = length - respinfo.loadedLenght; readsize = Math.Min(readsize, singlePkgMaxRead); len = ssl.Read(temp_responseBody, 0, readsize); if (len > 0) { memoryStream.Write(temp_responseBody, 0, len); respinfo.loadedLenght += len; } } } //解析chunked传输 else if (respinfo.headers.ContainsKey(Transfer_Encoding)) { Log("User chunked"); //读取长度 int chunkedSize = 0; byte[] chunkedByte = new byte[1]; //读取总长度 respinfo.loadedLenght = 0; do { string ctmp = ""; do { len = ssl.Read(chunkedByte, 0, 1); ctmp += Encoding.UTF8.GetString(chunkedByte); } while (ctmp.IndexOf(CT) == -1 && sw.ElapsedMilliseconds < timeout); chunkedSize = Tools.convertToIntBy16(ctmp.Replace(CT, "")); //chunked的结束0\r\n\r\n是结束标志,单个chunked块\r\n结束 if (ctmp.Equals(CT)) { continue; } if (chunkedSize == 0) { //结束了 break; } int onechunkLen = 0; while (onechunkLen < chunkedSize && sw.ElapsedMilliseconds < timeout) { //len = ssl.Read(responseBody, respinfo.loadedLenght, chunkedSize - onechunkLen); int readsize = chunkedSize - onechunkLen; readsize = Math.Min(readsize, singlePkgMaxRead); len = ssl.Read(temp_responseBody, 0, readsize); if (len > 0) { memoryStream.Write(temp_responseBody, 0, len); onechunkLen += len; respinfo.loadedLenght += len; } } //判断 } while (sw.ElapsedMilliseconds < timeout); } //connection close方式或未知body长度 else { Log("connection close or Unknow bodylenght"); while (sw.ElapsedMilliseconds < timeout) { while (sw.ElapsedMilliseconds < timeout) { if (client.Client.Poll(timeout, SelectMode.SelectRead)) { if (client.Available > 0) { //len = ssl.Read(responseBody, respinfo.loadedLenght, (1024 * 200) - respinfo.loadedLenght); int readsize = (1024 * 200) - respinfo.loadedLenght; readsize = Math.Min(readsize, singlePkgMaxRead); len = ssl.Read(temp_responseBody, 0, readsize); if (len > 0) { memoryStream.Write(temp_responseBody, 0, len); respinfo.loadedLenght += len; } } else { break; } } } } } byte[] responseBody = memoryStream.ToArray(); //如果是下载 if (respinfo.downloadMode > AxiDownLoadMode.NotDownLoad) { //判断是否gzip if (respinfo.isGzip) { respinfo.bodyRaw = unGzipBytes(responseBody, respinfo.loadedLenght); } else { respinfo.bodyRaw = responseBody; } // 使用Uri类解析URL Uri uri = new Uri(url); respinfo.fileName = Path.GetFileName(uri.LocalPath); } else { //判断是否gzip if (respinfo.isGzip) { respinfo.body = unGzip(responseBody, respinfo.loadedLenght, encod); } else { respinfo.body = encod.GetString(responseBody, 0, respinfo.loadedLenght); } } } } catch (Exception ex) { respinfo.Err = $"ex : {ex.ToString()}"; } finally { client?.Close(); sw.Stop(); respinfo.length = respinfo.loadedLenght; respinfo.runTime = (int)sw.ElapsedMilliseconds; respinfo.bTimeOut = sw.ElapsedMilliseconds >= timeout; //if (socket != null) //{ // clientSocket.Close(); //} respinfo.isDone = true; } } private static void doHeader(ref AxiRespInfo respinfo, ref string[] headers) { for (int i = 0; i < headers.Length; i++) { if (i == 0) { respinfo.code = Tools.convertToInt(headers[i].Split(' ')[1]); } else { String[] kv = Regex.Split(headers[i], ": "); String key = kv[0].ToLower(); if (!respinfo.headers.ContainsKey(key)) { //自动识别编码 if ("content-type".Equals(key)) { String hecnode = getHTMLEncoding(kv[1], ""); if (!String.IsNullOrEmpty(hecnode)) { respinfo.encoding = hecnode; } } if (kv.Length > 1) { respinfo.headers.Add(key, kv[1]); } else { respinfo.headers.Add(key, ""); } } } respinfo.isGzip = respinfo.headers.ContainsKey(Content_Encoding); } } public static string unGzip(byte[] data, int len, Encoding encoding) { string str = ""; MemoryStream ms = new MemoryStream(data, 0, len); GZipStream gs = new GZipStream(ms, CompressionMode.Decompress); MemoryStream outbuf = new MemoryStream(); byte[] block = new byte[1024]; try { while (true) { int bytesRead = gs.Read(block, 0, block.Length); if (bytesRead <= 0) { break; } else { outbuf.Write(block, 0, bytesRead); } } str = encoding.GetString(outbuf.ToArray()); } catch (Exception e) { Log("解压Gzip发生异常----" + e.Message); } finally { outbuf.Close(); gs.Close(); ms.Close(); } return str; } public static byte[] unGzipBytes(byte[] data, int len) { MemoryStream ms = new MemoryStream(data, 0, len); GZipStream gs = new GZipStream(ms, CompressionMode.Decompress); MemoryStream outbuf = new MemoryStream(); byte[] block = new byte[1024]; byte[] result; try { while (true) { int bytesRead = gs.Read(block, 0, block.Length); if (bytesRead <= 0) { break; } else { outbuf.Write(block, 0, bytesRead); } } result = outbuf.ToArray(); } catch (Exception e) { Log("解压Gzip发生异常----" + e.Message); result = new byte[0]; } finally { outbuf.Close(); gs.Close(); ms.Close(); } return result; } public static string getHTMLEncoding(string header, string body) { if (string.IsNullOrEmpty(header) && string.IsNullOrEmpty(body)) { return ""; } body = body.ToUpper(); Match m = Regex.Match(header, @"charset\b\s*=\s*""?(?[^""]*)", RegexOptions.IgnoreCase); if (m.Success) { return m.Groups["charset"].Value.ToUpper(); } else { if (string.IsNullOrEmpty(body)) { return ""; } m = Regex.Match(body, @"charset\b\s*=\s*""?(?[^""]*)", RegexOptions.IgnoreCase); if (m.Success) { return m.Groups["charset"].Value.ToUpper(); } } return ""; } private static void checkContentLength(ref AxiRespInfo respinfo, ref string request) { //重新计算并设置Content-length int sindex = request.IndexOf(CTRL); respinfo.reuqestHeader = request; if (sindex != -1) { respinfo.reuqestHeader = request.Substring(0, sindex); respinfo.reuqestBody = request.Substring(sindex + 4, request.Length - sindex - 4); int contentLength = Encoding.UTF8.GetBytes(respinfo.reuqestBody).Length; String newContentLength = Content_Length_Str_M + contentLength; if (request.IndexOf(Content_Length_Str_M) != -1) { request = Regex.Replace(request, Content_Length_Str_M + "\\d+", newContentLength); } else { request = request.Insert(sindex, "\r\n" + newContentLength); } } else { request = Regex.Replace(request, Content_Length_Str + "\\d+", Content_Length_Str_M + "0"); request += CTRL; } } private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } public static bool ParseURI(string strURI, ref bool bIsSSL, ref string strHost, ref string strIP, ref int Port, ref string strRelativePath) { string strAddressRet; string strPortRet; string strRelativePathRet; string strIPRet; /*string strProtocol = strURI.Substring(0, 7); if (strProtocol != "http://" || strProtocol != "https://") return false;*/ if (!strURI.ToLower().StartsWith("http://") || strURI.ToLower().StartsWith("https://")) return false; bIsSSL = strURI.ToLower().StartsWith("https://"); string strLeft = strURI.Substring(7, strURI.Length - 7); int nIndexPort = strLeft.IndexOf(':'); if (nIndexPort == -1) { if (bIsSSL) strPortRet = "443"; else strPortRet = "80"; int nIndexRelative = strLeft.IndexOf('/'); if (nIndexRelative != -1) { strAddressRet = strLeft.Substring(0, nIndexRelative); strRelativePathRet = strLeft.Substring(nIndexRelative, strLeft.Length - nIndexRelative); } else return false; } else { strAddressRet = strLeft.Substring(0, nIndexPort); int nIndexRelative = strLeft.IndexOf('/'); if (nIndexRelative != -1) { strPortRet = strLeft.Substring(nIndexPort + 1, nIndexRelative - (nIndexPort + 1)); strRelativePathRet = strLeft.Substring(nIndexRelative, strLeft.Length - nIndexRelative); } else return false; } strHost = strAddressRet; try { //IPHostEntry hostinfo = Dns.GetHostEntry(strAddressRet); //IPAddress[] aryIP = hostinfo.AddressList; //strIPRet = aryIP[0].ToString(); strIPRet = GetDnsIP(strAddressRet).ToString(); } catch { return false; } strIP = strIPRet; Port = int.Parse(strPortRet); strRelativePath = UrlEncode(strRelativePathRet); return true; } public static string UrlEncode(string str) { string sb = ""; List filter = new List() { '!', '#', '$', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '=', '?', '@', '_', '~' }; byte[] byStr = System.Text.Encoding.UTF8.GetBytes(str); //System.Text.Encoding.Default.GetBytes(str) for (int i = 0; i < byStr.Length; i++) { if (filter.Contains((char)byStr[i])) sb += (char)byStr[i]; else if ((char)byStr[i] >= 'a' && (char)byStr[i] <= 'z') sb += (char)byStr[i]; else if ((char)byStr[i] >= 'A' && (char)byStr[i] <= 'Z') sb += (char)byStr[i]; else if ((char)byStr[i] >= '0' && (char)byStr[i] <= '9') sb += (char)byStr[i]; else sb += (@"%" + Convert.ToString(byStr[i], 16)); } return sb; } class Tools { public static long currentMillis() { return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds; } /// /// 将16进制转换成10进制 /// /// 16进制字符串 /// public static int convertToIntBy16(String str) { try { Log($"convertToIntBy16 str- {str} lenght->{str.Length}"); if (str.Length == 0) return 0; return Convert.ToInt32(str, 16); } catch (Exception e) { Log($"convertToIntBy16 - {e.ToString()}"); } return 0; } public static String getCurrentPath(String url) { int index = url.LastIndexOf("/"); if (index != -1) { return url.Substring(0, index) + "/"; } else { return ""; } } /// /// 将字符串转换成数字,错误返回0 /// /// 字符串 /// public static int convertToInt(String str) { try { return int.Parse(str); } catch (Exception e) { Log("info:-" + e.Message); } return 0; } } class TimeOutSocket { private bool IsConnectionSuccessful = false; private Exception socketexception = null; private ManualResetEvent TimeoutObject = new ManualResetEvent(false); public int useTime = 0; public TcpClient Connect(string host, int port, int timeoutMSec) { Stopwatch sw = new Stopwatch(); sw.Start(); TimeoutObject.Reset(); socketexception = null; TcpClient tcpclient = new TcpClient(); //IPHostEntry hostinfo = Dns.GetHostEntry("emu.axibug.com"); //IPAddress[] aryIP = hostinfo.AddressList; //host = aryIP[0].ToString(); Log($"BeginConnect {host}:{port} timeoutMSec=>{timeoutMSec}"); tcpclient.BeginConnect(host, port, new AsyncCallback(CallBackMethod), tcpclient); if (TimeoutObject.WaitOne(timeoutMSec, false)) { if (IsConnectionSuccessful) { sw.Stop(); useTime = (int)sw.ElapsedMilliseconds; return tcpclient; } else { throw socketexception; } } else { tcpclient.Close(); throw new TimeoutException("TimeOut Exception"); } } private void CallBackMethod(IAsyncResult asyncresult) { try { IsConnectionSuccessful = false; TcpClient tcpclient = asyncresult.AsyncState as TcpClient; if (tcpclient.Client != null) { tcpclient.EndConnect(asyncresult); IsConnectionSuccessful = true; } } catch (Exception ex) { Log($"CallBackMethod - {ex.ToString()}"); IsConnectionSuccessful = false; socketexception = ex; } finally { TimeoutObject.Set(); } } } }