話說在很久很久以前。Web頁面與客戶的本地電腦Localhost通訊,有兩種方式:
1。Flash 2。ActiveX控件
由於Flash本人不是很了解,也給出不了什么示例代碼,
對於ActiveX控件來說,可以直接在在網絡上搜索“ActiveX控件”,就會有很多相關的答案
但是:
對於現代瀏覽器來說,以上兩種方式都通通不支持了
對於Flash來說,雖然現在瀏覽器還有支持,但是都不是默認加載Flash插件了
要用戶手工點同意才會加載。
對於ActiveX控件來說,只在IE瀏覽器里面才受支持,而且也要用戶同意,更別說現代瀏覽器了
所以說。對於現代的瀏覽器。要與本地電腦通訊。上面兩種方式已經行不通了。
那有沒有不要用戶點同意,就可以直接通過Web頁面與本地電腦通訊呢?
答案是當然有了。不然也不會有此文章了。
對於Web與服務器通訊,我們走的是HTTP協議。這也是所有瀏覽器都支持的
也不會管現在瀏覽器和遠古時代的瀏覽器也都支持HTTP協議。
那么
如果Web要與本地電腦通訊,只要Web與本地電腦走HTTP協議通訊。問題不就解決了嗎?
那怎么實現呢?
既然要與本地電腦走HTTP協議通訊,那本地就必需要有一個支持HTTP協議的通道
平常我們與遠程服務器通訊是怎么訪問的,比如說百度吧,我們輸入http://www.baidu.com就能正常打開了
那我們本地怎么辦呢,我們做開發測試的時候,是不是輸入:http://localhost 或者 http://127.0.0.1是不是就訪問的我們本地電腦
那么,我們在頁面里向本地發送一個請求。會有什么結果?
我們來實驗一下:
首先,既然要與本地服務器通訊。那么我們在本地要監聽一下本地的http協議通訊,代碼如下
namespace LocalApp { class Program { public static HttpListener listener = new HttpListener(); static void Main(string[] args) { listener.Start(); listener.Prefixes.Add("http://127.0.0.1:8976/");//我們監聽本地電腦8976端口的HTTP協議 Thread t = new Thread(new ThreadStart(clientListener)); t.Start(); while (true) { string s = Console.ReadLine(); listener.Stop(); listener.Close(); } } public static void clientListener() { while (true) { try { //如果收到講求,我們就開啟一個線程去處理請求 HttpListenerContext request = listener.GetContext(); ThreadPool.QueueUserWorkItem(processRequest, request); } catch (Exception e) { Console.WriteLine(e.Message); } } } public static void processRequest(object listenerContext) { try { var context = (HttpListenerContext)listenerContext; var dicPar = new Dictionary<string, string>(); var listPar = new List<string>(); //拿到請求參數 foreach (var item in context.Request.QueryString.AllKeys) { listPar.Add(String.Format("{0}={1}", item, context.Request.QueryString[item])); dicPar.Add(item, context.Request.QueryString[item]); } //設置返回值 var resultJson = JsonConvert.SerializeObject(dicPar); Console.WriteLine(String.Join(Environment.NewLine, listPar)); context.Response.StatusCode = (int)HttpStatusCode.OK; context.Response.ContentLength64 = System.Text.Encoding.UTF8.GetByteCount(resultJson); context.Response.ContentType = "application/json"; context.Response.ContentEncoding = Encoding.UTF8; context.Response.Headers.Add("Access-Control-Allow-Origin", "*"); //返回結果 System.IO.Stream output = context.Response.OutputStream; using (StreamWriter writer = new StreamWriter(output)) { writer.Write(resultJson); writer.Close(); } } catch { } } } }
上面的代碼就是監聽本地電腦8976端口的HTTP協議,
如果收到請求。就提取參數,然后以Json的形式返回
那么,我們寫一個Html頁面,向本地8976端口發送數據會出現什么情況
代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script src="Scripts/jquery-3.3.1.js"></script> </head> <body> <form id="form1" enctype="application/x-www-form-urlencoded"> <div><label>參數1:<input type="text" name="Par1" /></label></div> <div><label>參數2:<input type="text" name="Par2" /></label></div> <div><button type="button" onclick="btnSubmit()">提交</button></div> </form> <script> function btnSubmit() { $.get("http://127.0.0.1:8976/", $("#form1").serialize(), function (result) { console.log(result); }, "json"); } </script> </body> </html>
打開Chrome瀏覽器做一下測試。結果如下:
頁面成功的發起了請求,本地電腦APP也監聽到了Web發來了請求,參數也都拿到了。
是不是我們就可以用這種方式用Web端來調用本地電腦的資源了
以知問題:
當我們的站點是以https訪問的時候,如果用http去請求本地資源,而不是用https去請求的話,有些瀏覽器會報Mixed Content錯誤
但是在新版本的谷歌與火狐已經解決了此問題,參考:https://bugzilla.mozilla.org/show_bug.cgi?id=903966
另外一個有一個秘密,一般人我不告訴他
你們知道當你們在本地登錄了QQ后,然后打開QQ的Web站點,他為什么就能自動知道你當前登錄的QQ嗎?
沒錯,他也用了這種方案與QQ通訊,從而知道你登錄了哪個QQ,這樣才會有此快速登錄的功能
思維擴展:
這種訪案只能是Web發起請求,本地電腦接受請求。只支持單一方向通訊,
那么,有沒有支持雙向通訊的方案呢?(Web到本地,本地到Web)
如果有知道答案的。可以在此博文下說出你的想法。