2015年11月5日 星期四

網頁開發人員應了解的 HTTP 狀態碼-轉貼

轉自

The Will Will Web

http://blog.miniasp.com/post/2009/01/16/Web-developer-should-know-about-HTTP-Status-Code.aspx

我想一般人對於 HTTP 狀態碼(Status Code) 多少會有些印象,例如 HTTP 200 代表網頁正常、404 代表找不到網頁。但似乎一般人大多不曾仔細研究所有 HTTP 狀態碼的定義,以及 HTTP 狀態碼到底對開發人員來說有何影響。
我承認,就算你完全不瞭解 HTTP Status Code 也可以開發出一個網站,若你寫的是 ASP.NET 也通常不會影響你的開發作業,因為 ASP.NET 已經包裝的很好了。
但是若網站架構越來越大,需要微調的時候,或是系統整合需要整合到更底層的網路作業時,若不瞭解這些代碼的意義 (或根本不知道有 HTTP 狀態碼這玩意),可能很容易就會遇到瓶頸,尤其是在除錯的時候更加明顯,我就曾經看過有人因為網頁收到 404 的錯誤訊息還一直在找程式哪裡出錯了,完全沒想到是自己網址打錯。
HTTP 狀態碼指的是從伺服器端回應(HTTP Response)的狀態,對於狀態的分類可區分三個層級,分別用三個數字表示,第一個數字為大類、第二個數字為中類、第三個數字為小類。完整的狀態碼定義可以參考 RFC 2616 Hypertext Transfer Protocol -- HTTP/1.1 的 10 Status Code Definitions 章節,裡面有完整且詳盡的說明。
不過在 IIS 中有不少微軟自訂的擴充狀態碼,格式類似 404.0 這樣,清楚的狀態碼對於除錯很有幫助。
HTTP 狀態碼大致分成 5 類 (粗體表示),完整的狀態碼概述如下:
  • 1xx - 參考資訊 (Informational)
    這些狀態碼代表主機先暫時回應用戶端一個狀態,所以在接收一般的回應之前,用戶端應準備接收一個或多個 1xx 的回應。我以前在寫 ASP 的時候比較有看到 IIS 使用到這些狀態碼回應,在 Apache 的環境我還未曾遇到過。
    • 100 - 繼續。
    • 101 - 切換通訊協定。
  • 2xx - 成功 (OK)
    這類的狀態碼表示伺服器成功接收到用戶端要求、理解用戶端要求、以及接受用戶端要求。
    • 200 - 確定。 用戶端要求成功。
    • 201 - 已建立。
    • 202 - 已接受。
    • 203 - 非授權資訊。
    • 204 - 無內容。
    • 205 - 重設內容。
    • 206 - 部分內容。
    • 207 - 多重狀態 (WebDAV) -- 這好像只有在 IIS 中才有,HTTP/1.1 並沒有定義這個狀態。這狀態會出現在可以包含多個不同回應代碼 (視子要求數量而定) 的 XML 訊息之前。
  • 3xx - 重新導向 (Redirection)
    用戶端瀏覽器必須採取更多動作才能完成要求。例如:瀏覽器可能必須重新發出 HTTP Request 要求伺服器上的不同頁面。
    • 301 - 要求的網頁已經永久改變網址。此狀態要求用戶端未來在連結此網址時應該導向至指定的 URI。
    • 302 - 物件已移動,並告知移動過去的網址。針對表單架構驗證,這通常表示為「物件已移動」。 要求的資源暫時存於不同的 URI 底下。 由於重新導向可能偶而改變,用戶端應繼續使用要求 URI 來執行未來的要求。 除非以 Cache-Control 或 Expires 標頭欄位表示,此回應才能夠快取。 
      ASP.NET 預設的 Response.Redirect 方法,就是以 302 Found 做回應。
    • 303 - 通知 Client 連到另一個網址去查看上傳表單的結果(POST 變成 GET),當使用程式作網頁轉向時,會回應此訊息。
      在 ASP.NET 中要輸出 HTTP 303 轉向的程式碼如下:
      Response.StatusCode = 303;
      Response.RedirectLocation = "/PageB.aspx";
    • 304 - 未修改。用戶端要求該網頁時,其內容並沒有變更,應該回傳 304 告知網頁未修改。此時用戶端僅需要取得本地快取(Local Cache)的副本即可。
    • 305 - 要求的網頁必須透過 Server 指定的 proxy 才能觀看 ( 透過 Location 標頭 )
    • 306 - (未使用) 此代碼僅用來為了向前相容而已。
    • 307 - 暫時重新導向。要求的網頁只是「暫時」改變網址而已。
  • 4xx - 用戶端錯誤 (Client Error)
    這代表錯誤發生,且這錯誤的發生的原因跟「用戶端」有關。例如:用戶端可能連結到不存在的頁面、用戶端的權限不足、或可能未提供有效的驗證資訊(輸入的帳號、密碼錯誤)。下次看到 4xx 的回應千萬不要傻傻的一直查程式哪裡寫錯誤了(不過也有可能是程式造成的)。
    • 400 - 錯誤的要求。
    • 401 - 拒絕存取。 IIS 定義數個不同的 401 錯誤,以表示更詳細的錯誤原因。 這些特定的錯誤碼會顯示在瀏覽器中,但不會顯示在 IIS 記錄檔中:
      • 401.1 - 登入失敗。
      • 401.2 - 因為伺服器設定導致登入失敗。
      • 401.3 - 因為資源上的 ACL 而沒有授權。
      • 401.4 - 篩選授權失敗。
      • 401.5 - ISAPI/CGI 應用程式授權失敗。
      • 401.7 - Web 伺服器上的 URL 授權原則拒絕存取。 這是 IIS 6.0 專用的錯誤碼。
    • 403 - 禁止使用。 IIS 定義數個不同的 403 錯誤,以表示更詳細的錯誤原因:
      • 403.1 - 禁止執行存取。
      • 403.2 - 禁止讀取存取。
      • 403.3 - 禁止寫入存取。
      • 403.4 - 需要 SSL。
      • 403.5 - 需要 SSL 128。
      • 403.6 - IP 位址遭拒。
      • 403.7 - 需要用戶端憑證。
      • 403.8 - 網站存取遭拒。
      • 403.9 - 使用者過多。
      • 403.10 - 設定無效。
      • 403.11 - 密碼變更。
      • 403.12 - 對應程式拒絕存取。
      • 403.13 - 用戶端憑證已撤銷。
      • 403.14 - 目錄清單遭拒。
      • 403.15 - 超過用戶端存取授權數量。
      • 403.16 - 用戶端憑證不受信任或無效。
      • 403.17 - 用戶端憑證已經過期或尚未生效。
      • 403.18 - 無法在目前的應用程式集區中執行要求的 URL。 這是 IIS 6.0 專用的代碼。
      • 403.19 - 無法在這個應用程式集區中執行用戶端的 CGI。 這是 IIS 6.0 專用的代碼。
      • 403.20 - Passport 登入失敗。 這是 IIS 6.0 專用的錯誤碼。
    • 404 - 找不到。
      • 404.0 - (無) – 找不到檔案或目錄。
      • 404.1 - 無法在要求的連接埠上存取網站。
      • 404.2 - 網頁服務延伸鎖定原則阻止這個要求。
      • 404.3 - MIME 對應原則阻止這個要求。
    • 405 - 用來存取這個頁面的 HTTP 動詞不受允許 (方法不受允許)。
    • 406 - 用戶端瀏覽器不接受要求頁面的 MIME 類型。
    • 407 - 需要 Proxy 驗證。
    • 412 - 指定條件失敗。
    • 413 - 要求的實體太大。
    • 414 - 要求 URI 太長。
    • 415 - 不支援的媒體類型。
    • 416 - 無法滿足要求的範圍。
    • 417 - 執行失敗。
    • 423 - 鎖定錯誤。
  • 5xx - 伺服器錯誤 (Server Error)
    這代表錯誤發生,且這錯誤發生的原因跟「伺服器」有關。伺服器因為發生錯誤或例外狀況(Exception)而無法完成要求(Request)時,就會回應 5xx 的錯誤,且這肯定跟伺服器有關。
    • 500 - 內部伺服器錯誤。
      • 500.12 - 應用程式正忙於在 Web 伺服器上重新啟動。
      • 500.13 - Web 伺服器過於忙碌。
      • 500.15 - 不允許直接要求 Global.asa。
      • 500.16 – UNC 授權認證不正確。 這是 IIS 6.0 專用的錯誤碼。
      • 500.18 – 無法開啟 URL 授權存放區。 這是 IIS 6.0 專用的錯誤碼。
      • 500.19 - 此檔案的資料在 Metabase 中設定不當。
      • 500.100 - 內部的 ASP 錯誤。
    • 501 – 標頭值指定未實作的設定。
    • 502 - Web 伺服器在作為閘道或 Proxy 時收到無效的回應。
      • 502.1 - CGI 應用程式逾時。
      • 502.2 - CGI 應用程式中發生錯誤。
    • 503 - 服務無法使用。 這是 IIS 6.0 專用的錯誤碼。
    • 504 - 閘道逾時。
    • 505 - 不支援的 HTTP 版本。

2015年11月2日 星期一

跨執行&委派

最近在寫執行緒,參考了許多文章,這是篇簡單又實用的文章,
轉貼出處http://toyo0103.blogspot.tw/2012/03/c-ui.html

作者說的很清楚,執行緒是拿來做重覆、繁雜的事,將資源留給
主程式去運作,執行緒執行到定點時定時回報
但是他忘了說,要記得thread作完它的工作後,要記得釋放資源,
不要被它lock住了,而讓程式變殭屍。
因為我們用的是C#,我的老大最愛說的一句話是『不要相信c#的
自動資源釋放,它是在資源不夠的時候,才會回收
資源。」總歸一句話,出來混總是要還的;所以寫自已寫的程式,
資源要自己收。


寫了四年的程式,第一次寫執行緒,第一次使用委派,真的是老菜鳥。
在執行緒中要更新win form 頁面,結果 GG 了,這是什麼???
跨執行緒作業無效 存取控制項 'textbox1' 時所使用的執行緒與建立控制
項的執行緒不同。
原來這是多執行緒的天條,不同的執行緒,不可以跨界去使用別人的UI。
我的解決方法,在拜完G神之後還是有看沒懂

多數人都是轉載這篇

如何跨執行緒存取UI
當我試著用WinFrom寫多執行緒時,卻出現了以下錯誤訊息
跨執行緒作業無效: 存取控制項 'textBox1' 時所使用的執行緒與建立控制項的執行緒不同。
詢問高手後有三種方法解決:
1.Form.CheckForIllegalCrossThreadCalls = False
2.建立委派
第一種方法,據說不安全,但我也不曉得哪裡不安全,但用起來還蠻方便的。
第二種方法,比較正統使用委派的方式,若爾後需要改任何控制項的文字時(需有text屬性的),呼叫 myU即可。


private delegate void myUICallBack(string myStr, Control ctl);
  private void myUI(string myStr, Control ctl)
  {
  if (this.InvokeRequired)
  {
  myUICallBack myUpdate = new myUICallBack(myUI);
  this.Invoke(myUpdate, myStr, ctl);
  }
  else
  {
  ctl.Text = myStr;
  }
 

這實在是小的愚昧,我認識它,它也認識我,只是我讀不懂它。
只能硬用了。

最近有點知道委派是怎麼回事了,若是有錯,請各位先進,不吝指教。
原來委派有2種方式,一種是使用事件方式,在註冊事件後就可以呼叫它
使用它了,可以參考余小章 @ 大內殿堂的文章
http://www.dotblogs.com.tw/yc421206/archive/2009/02/16/7206.aspx

另一種就是http://toyo0103.blogspot.tw/2012/03/c-ui.html中的委派,
直接呼叫該物件的function,介由this.InvokeRequired判斷是否是同一個thread
若不是,則呼叫委派,由該物件重新執行function,我想大約也是讓你有聽沒有懂;
你可以依步驟這樣做。

1.在要顯示UI的form中,寫好你要執行的動作;如:

  public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void ReflashPanelPage(List<Release> Rlist)
        {
            TextBox txtbox = new TextBox();

            txtbox = (TextBox)Utility.ControlFind(this.pl_Main, "txt_descript");
           int Row =Rlist.count()-1;
            foreach (Release Item in Rlist)
            {
                //輪到的 Panel變色
                Panel Pl = (Panel)Utility.ControlFind(this.pl_Main, Item.Name);

                Pl.BackColor = System.Drawing.Color.LightYellow;
                Pl.Size = new System.Drawing.Size(192, Pl.Size.Height);
                Pl.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;

                txtbox.Text = null;
                txtbox.Visible = true;
                txtbox.Text += "Version";
                txtbox.Text += Item.Version + Environment.NewLine;
                txtbox.Text += Item.Description;


                if (Row != 1)
                {
                    Pl.BackColor = System.Drawing.Color.Transparent;
                    Pl.Size = new System.Drawing.Size(180, Pl.Size.Height);
                    Pl.BorderStyle = System.Windows.Forms.BorderStyle.None;
                }
               Row--;

            }
        }
    }

我要傳入List<Release>,輪到的 Panel變色,
但是呼叫它的另一個物件中的thread

2.
 public class Updater : IDisposable { public Form1 F1 = new Form1(); public Updater() { ParameterizedThreadStart updaterThread = new ParameterizedThreadStart(UpdateProcess); Thread ThreadObj = new Thread(updaterThread); ThreadObj.Start(); } public void UpdateProcess() { List<Release> ReleasList = getReleaseItem(); F1.ReflashPanelPage(ReleasList); //在這裡由update 呼叫它 } }

這時候程跑到這一定會出錯的 跨執行緒作業無效 存取控制項 '‧‧‧‧‧' 時所使用的執行緒與建立控制項的執行緒不同。因為不能執行緒來更新UI,這是執行緒的天條,不可侵犯。
所以我們做第3步

3.在form1中建立delegate ,並使用它

  public partial class Form1 : Form
    {

   private delegate void ReflashUpdateUI(List<Release> Update);
        public Form1()
        {
            InitializeComponent();
        }
.....
.....
.....

 public void UpdateUIChange(List<Release> Update)
        {
            //判斷物件是否在同一個執行緒上
            if (this.InvokeRequired)
            {
                //當InvokeRequired為true時,表示在不同的執行緒上,所以進行委派的動作!!
                ReflashUpdateUI UI = new ReflashUpdateUI(UpdateUIChange);
                this.Invoke(UI, Update);
            }
            else
            {
                ReflashPanelPage(Update);
            }

        }

}

5.修改thread呼叫 delegate 來執行UI 更新的功能

   public void UpdateProcess() { List<Release> ReleasList = getReleaseItem(); F1.UpdateUIChange(ReleasList); //在這裡由update 呼叫它 }


以上完成

第二種方式,是我比較常用的委派,我覺得它比較簡單,一樣在form 中寫好要執行變更UI 的動作後,宣告好委派後,再寫好觸動委派的function  ex :UpdateProcess()
,再在thread 中呼叫 UpdateProcess,由InvokeRequired來判斷是否是同一個執行緒,若是不同則執行委派。



參考出處:http://www.dotblogs.com.tw/shinli/archive/2015/04/16/151076.aspx
參考出處 http://www.dotblogs.com.tw/yc421206/archive/2009/02/13/7141.aspx
參考出處 http://code2study.blogspot.tw/2011/09/c.html