1. 程式人生 > >TCP的狀態轉化過程(11中狀態)以及TIME_WAIT狀態

TCP的狀態轉化過程(11中狀態)以及TIME_WAIT狀態

TCP中的三次握手,四次揮手是我們所熟知的,可是,我們熟悉裡面的各種狀態嗎???

(SYN_SENT,   ESTABLISHED,    CLOSE_WAIT.............),試問一句,我們瞭解裡面的狀態轉化嗎???

1,大家先看一個簡單的通訊圖(圖片轉載與:UNIX網路程式設計,page:36,圖2-5)

     

     可以很明顯的看到,在通訊雙方,客戶端,服務端的狀態變化過程

     有人可能會說:我們上面不是說,有11中狀態嗎??為什麼到啦這裡變成了只有10中

     (1,(主動開啟:SYN_SENT)        2,ESTABLISHED        3,(主動關閉:FIN_WAIT_1)     4,FIN_WAIT_2

       5,TIME_WAIT        6,SYN_RCVD     7,CLOSE_WAIT(被動關閉)     8,LAST_ACK    9,CLOSED

       10,LISTEN)

       為什麼不是11個呢???

       哈哈,其實還有一種狀態叫做:CLOSING(這個狀態產生的原因比較特殊,後面分析)

      接下來我們分析一下,這些狀態的變化過程,,,

           主動套介面:用來發起連線                            被動套介面:用來接受連線

      1,對於伺服器端來說:

           當呼叫socket函式建立一個套接字時,狀態是CLOSED

,它被假設為一個主動套接字,也就是說,它是一個

           將呼叫connect發起連線的客戶套接字。listen函式把一個未連線的套接字轉化成一個被動套接字,指示核心

           應接受指向該套接字的連線請求。結合TCP的狀態轉化圖:

           呼叫listen函式導致套接字從:CLOSED狀態轉化為:LISTEN狀態

       2,對於客戶端來說:

             呼叫socket函式建立一個套介面時,狀態也是CLOSED,同樣的,它也被假設為一個主動套接字,緊接著,調

             用connect主動開啟套介面,並且一直阻塞著,等待三次握手的完成,我們把這個狀態稱之為:主動套介面

             當客戶端發起了三次握手的第一次(SYN   J,MSS = 536)的時候,套介面的狀態變成了:

             SYN_SENT(主動開啟)

       3,對於伺服器端而言,呼叫了listen之後,然後狀態就變成了LISTEN狀態,接著呼叫accept函式,使自身一直

            保持阻塞的狀態,直到三次握手的第一次來到(來自TCP協議棧的TCP的第一個分節),即接收到(SYN  J,

            MSS = 536),此刻狀態由:LISTEN轉變為SYN_RCVD

       4,對於客戶端來說,剛才傳送了TCP協議棧中TCP三次握手的第一個分節,此刻應該接受來自伺服器傳送過來的

             TCP三次握手的第二個分節,這時伺服器傳送過來:(SYN K, ACK J+1, MSS = 1460),此刻,伺服器

             的狀態不變,還是SYN_RCVD,然後,客戶端接受伺服器傳送過來的TCP三次握手的第二次分節,此刻狀態

             由之前的:SYN_SENT轉變為ESTABLISHED,(客戶端已經建立完成),這時,connect函式返回

       5,然後客戶端保持ESTABLISHED狀態,並且發出TCP協議棧中TCP三次握手的第三個分節(ACK  K+1)

             服務端的狀態由:SYN_RCVD轉變為:ESTABLISHED,從未完成的佇列中取出隊首的第一個連線放在已完成

             佇列,這樣accept函式就會返回。

             此刻,兩者都建立完成,這個時候可以完成通訊了

       6,那麼接下來就是連線終止的四次握手,,,

             當雙方都變成ESTABLISHED狀態之後,雙方就可以通訊了,在雙方通訊的過程中,由於狀態都沒有變化,

             所以這裡,我們暫且不討論。在通訊的時候呢,雙方都可以主動發起關閉,那麼:我們假定客戶端發起一個

             關閉請求(呼叫close函式):會向服務端傳送一個TCP分節(TCP協議棧中四次握手的的第一個分節:

             FIN M)然後客戶端的狀態會變成:FIN_WAIT_1(主動關閉)此刻,服務端接收到這個TCP分節後,

            並且會對剛才發過來的連線進行確認(ACK M+1),服務端的狀態會變成 CLOSE_WAIT(被動關

             閉)當,客戶端接收到這個確認之後(ACK M+1),客戶端的狀態轉變 

             為:FIN_WAIT_2   , 只有當服務端的read函式返回為0的時候,服務端才需要,也是才可以發起關閉請求(FIN 

             N),傳送完成之後,就變成了:

             LAST_ACK,       當客戶端接受到了這個關閉請求之後,狀態會變成了:TIME_WAIT(會經過

             2MSL(TCP報文端最大生存週期的兩倍時間)之後,轉變為:CLOSED),緊接著客戶端會發送

             最後一次確認:(ACK N+1),等到服務端接收到這個確認後,服務端的狀態會變成:CLOSED

             關於CLOSING:

             該狀態產生的原因是:對於客戶端和服務端而言,兩者同時關閉的情況(這種情況並不多見),如下圖:

            

、              兩者同時關閉,後狀態同時變成了FIN_WAIT_1,然後當另外一端接收到關閉分節後,狀態同時變成CLOSING,然後都對剛才那個分節進行確認,當對端收到之後,兩者又都變成了TIME_WAIT,

                  所以說:在關閉的過程中,不一定可以必須要經過FIN_WAIT_2這個狀態。。。。。。。。。。。。

關於TIME_WAIT:

            1,我們可以從上面的狀態分析中得知,對於TIME_WAIT狀態而言,是執行主動關閉的那端經歷了這個狀態。

                   該端點停留在這個狀態的持續時間是最長分節生命期(MAXIMUM  SEGMENT  LIFETIME, msl)的兩

                    倍,有時候稱之為:2MSL

                    任何TCP實現都必須為MSL選擇一個值,RFC1122的建議值是2分鐘,而源自Berkeley的實現傳統上改用

                     30秒這個值,又因為:資訊的傳送是需要一個來回,著也就說明,TIME_WAIT狀態的持續時間是1分鐘

                     到4分鐘之間。而MSL是任何IP資料報能夠在因特網中存活的最長時間。我們也知道這個時間是有限的,

                     因為每個資料報含有一個跳限(hop limit)的8位欄位,它的最大值是255。儘管這是一個跳數限制而不是

                     真正的時間限制,我們仍然假設:

                     具有最大跳限(255)的分組在網路中存在的時間不可能超過MSL秒。。。。。

                     分組在網路中“迷途”通常是路由異路的結果。某個路由器崩潰或某兩個路由器之間的某個鏈路斷開時,路由

                     協議需要花數秒鐘到數分鐘的時間才能穩定並找出另一條通路。在這段時間內可能發生路由迴圈(

                     路由器A把分組傳送給路由器B,而B再把它們傳送給A),我們關心的分組可能就此陷入這樣的迴圈。

                     假設迷途的分組是一個TCP分節,在它迷途期間,傳送端TCP超時重傳該分組,而重傳的分組卻通過某條

                     候選路徑到達最終目的。然而不久後(自迷途的分組開始其旅程起最多MSL秒以內)路由迴圈修復,早先

                     迷失在這個迴圈中的分組最終也被送到目的地。TCP必須正確處理這些重複的分組。

                     TIME_WAIT狀態存在的兩個理由:

                     1,可靠的實現TCP全雙工連線的終止(更好的完善TCP的可靠性)

                     2,允許老的重複分節在網路中消逝

                     關於第一點:假設最終的ACK丟失了來解釋(並不能保證傳輸的可靠行)。伺服器將重新發送它的最終的

                     那個FIN, 因此客戶必須維護狀態資訊,以允許它重新發送那個ACK。要是客戶不維護狀態資訊,它將

                     響應以一個RST(另外一種型別的TCP分節),該分節將被伺服器解釋成一個錯誤。如果TCP打算執行所

                     有必要的工作以徹底終止某個連線上兩個方向的資料流(即全雙工關閉),那麼它必須正確處理連線終止

                     序列4個分節中任何一個分節丟失的情況。本例子也說明了為什麼執行主動關閉的那一端是處於

                     TIME_WAIT的那一端;因為可能不得不重傳最終的那個ACK的就是那一端。

                     關於第二點:我們假設在12.106.32.254的1500埠和206.168.112.219的21埠之間有一個TCP連線。我

                     們關閉這個連線,過一段時間後在相同的IP地址和埠之間建立另一個連線。後一個連線稱為前一個連線

                     的化身,因為他們的IP地址和埠號相同。TCP必須防止來自某個連線的老的重複分組在該連線已終止後

                    再現,從而被誤解成屬於同一個連線的某個新的化身。為做到這一點,TCP將不給處於TIME_WAIT狀態

                    的連線發起新的化身。既然TIME_WAIT狀態的持續時間是MSL的2倍,這就足矣讓某個方向上的分組最多

                    存活MSL秒即被丟棄,另一個方向上的應答最多存活MSL秒也被丟棄。通過實施這個規則,我們就能保證

                    每成功建立一個TCP連線時,來自該連線先前化身的老的重複分組都已在網路中消逝了。。。。

                    大家可以過來看看!!!

                    當我們僅僅開啟服務端之後(埠號為5188),我們來看看所處的狀態。

                    開啟服務端:

                   

                    呼叫命令檢視所有的網路狀態:netstat

                    

                     然後,我們通過命令:摘取有關tcp的狀態:netstat  -an |grep tcp

                    

                     緊接著為了刪減出有效的資訊,我們只需要tcp協議,5188這個埠,我們可以這樣做:

 netstat -an|grep tcp|grep 5188
                     

                     嗯嗯,此刻,可以看到,我們這裡的狀態是處於LISTEN,呼叫的accept函式還是在阻塞著,等待著返回。

                     這時,我們再次開啟客戶端,繼續觀察一下狀態:

                    

                     然後,我們繼續呼叫之前的命令:

netstat -an|grep tcp|grep 5188

                    

                     當客戶端一開啟,那麼就完成了TCP的建立,這裡,我們可以看到有兩個是:ESTABLISHED

                     其中第二行的42555表示的是客戶端所開啟的埠,5188是服務端所開啟的埠,客戶端連向了伺服器端

                     由於我們上面的測試是在同一臺主機上的,所以會出現上面的三種資訊

                     而對於其他的狀態而言,只是因為狀態的轉化時間非常短(三次握手,四次揮手完成的特別快),我們不

                     去探究具體的狀態,,,

  1,查詢伺服器程序:

ps  -ef | grep echoserv


分析其pid號,知道了我們此刻開啟的是中間的這個服務端(21858,21849)

所以,此刻,我們殺死這個程序:

kill -9  21858


到啦這裡,我們再次檢視一下狀態:

至於為什麼會產生一個FIN_WAIT2,   而不是TIME_WAIT狀態呢,,,,這是因為:我們程式中是這樣處理的,我們

的服務端關閉之後,然後客戶端接收到啦這個分節,並向服務端傳送了當前的分節確認,然後自己阻塞在了從鍵盤獲

取字元的這個位置,並不能執行到函式read處去,也就是說,

read函式壓根就不會返回0,所以客戶端就不會重新向服務端重新發送關閉連線的分節,也就停留在此刻了,同樣的,

服務端接受到啦確認分節,那麼自己的狀態就變成了FIN_WAIT_2,這樣就解釋的通了,哈哈哈

以下是:我們的客戶端處理程式:

void echo_cli(int sock)
{
                                                                                                                                                
        char sendbuf[1024] = {0};
        char recvbuf[1024] = {0};

        while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
        {
                writen(sock, sendbuf, strlen(sendbuf));

                int ret = readline(sock, recvbuf, sizeof(recvbuf));
                
                if(ret == -1)
                        ERR_EXIT("READline");
                else if(ret == 0)
                {
                        printf("client close \n");      
                        break;
                }
                
                fputs(recvbuf, stdout);      //fgets接受到的資料,預設說明是存在換行符的
                memset(sendbuf, 0 , sizeof(sendbuf));
                memset(recvbuf, 0 , sizeof(recvbuf));
        }

        close(sock);
}

此刻,如果我們再重新輸入字元,然後就會執行到read函式處,由於對方已經關閉,對端會接收到(四次揮手)的

第一個分節(FIN),然後read返回0,從上面函式可以看出,程式執行break,然後繼續執行close(sock)

而對於客戶端先關閉的情況,,,則是這個樣子的,,,

同理,先開啟服務端,再開啟客戶端,,,

進去之後,直接按:CTRL + C,使客戶端退出,我們檢視一下狀態:

可以知道,出現了TIME_WAIT狀態,,,

同樣的,這裡,我們也需要檢視一下echoserv具體的實現:

void echo_serv(int conn)
{
        char recvbuf[1024];
        while(1)
        {
                memset(recvbuf, 0, sizeof(recvbuf));
                int ret = readline(conn, recvbuf, 1024);
                if(ret == -1)
                        ERR_EXIT("READLine");
                
                if(ret == 0)
                {
                        printf("client close\n");       
                        break;
                }
                        
                fputs(recvbuf, stdout);
                writen(conn, recvbuf, strlen(recvbuf));  
        }
}

出現這個狀態也是比較簡單,因為:客戶端結束了之後,服務端開始執行readline(裡面封裝了read),read 返回為0

不會阻塞,緊接著就執行close,會繼續傳送一個fin分節,,所以會出現後面的TIME_WAIT狀態啦,,,

我們的伺服器端會處於TIME_WAIT狀態,這時如果我們繼續開啟伺服器會出現:地址佔用,

如果,我們不使用REUSEADDR的話,如果我們使用這個REUSEADDR,並且設定選項的話,setsockopt的話,那麼

我們可以隨時開啟伺服器,不用等待2MSL個時間

關於RST分節,

1,對於RST分節,其實是這個樣子的,我們開啟服務端,客戶端,然後關閉服務端(會向客戶端傳送一個FIN 分節)

      ,但是這個時候,我們的客戶端是阻塞在fgets函式的,我們從鍵盤給一個字串,讓其滿足fgets函式,執行到write

      函式,將剛才的字串輸出給服務端,由於剛才的服務端已經終止了並且傳送了一個FIN,說明不能在傳送

      新的段,並且也不能接受對端的資料,由於此時服務端已經終止,所以上面客戶端傳送給服務端的資訊,也就找不

      到歸宿這個時候(對方程序不存在了),TCP協議棧就會發送一個RST的tcp分節過去。如果這個時候,我們在呼叫

      write() 函式去讀取的話,那麼就會產生SIGPIPE,

       程式如下:

 while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
        {

        //      writen(sock, sendbuf, strlen(sendbuf));
                write(sock , sendbuf, 1);      //分兩次傳送,先發送1個,然後在傳送剩餘的
                write(sock , sendbuf + 1, strlen(sendbuf) - 1);

                int ret = readline(sock, recvbuf, sizeof(recvbuf));
                
                if(ret == -1)
                        ERR_EXIT("READline");
                else if(ret == 0)
                {
                        printf("client close \n");      
                        break;
                }
                
                fputs(recvbuf, stdout);      //fgets接受到的資料,預設說明是存在換行符的
                memset(sendbuf, 0 , sizeof(sendbuf));
                memset(recvbuf, 0 , sizeof(recvbuf));
        }

可以看到,上面我們呼叫了兩次的write函式,第一次write函式(傳送字元的時候),對面的程序已經不在了,TCP

協議棧會發送一個RST分節,緊接著我們再次呼叫了write函式,此刻就產生了一個SIGPIPE的訊號中斷,直接終止當

前程序,倘使不退出程式的話,那麼read會返回0(readline中封裝著read),所以ret等於0,應該會列印client  close

,但是我們的程式並沒有列印。。。。。

(開啟相應的客戶端,服務端)

觀察狀態:

服務端關閉:

觀察狀態:

給客戶端一個字串,滿足fgets函式

程式直接退出了,所以看得出來,並沒有列印client  close

所以說,我們上面的分析是合理的。。。。。。

接下來我們修改一下程式:

<span style="color:#000000;">void handle_sigpipe(int sig)
{
        printf("recv is a sig = %d\n", sig);    
}


int main()
{                                                                                                                                               

        signal(SIGPIPE, handle_sigpipe);
        int sock;
        if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
                ERR_EXIT("socket");</span>
同樣的道理,我們來執行一下程式:

這裡還能輸出:client  close,為什麼呢???這是因為產生了sigpipe中斷訊號後,我們對中斷訊號進行了處理了,所以不會退出程式了

同樣的,我們來檢視一下這個:sig = 13

可以看到,這裡的正是sigpipe訊號

上面看啦這麼多,我們貌似好像看到了用kill殺死一個程序和CTRL + C,我們來看看區別!!!

同理,開啟客戶端,服務端

檢視狀態:


呼叫CTRL + C,關閉伺服器

接著我們繼續檢視狀態

如果我們:呼叫kill殺死相應的服務端程序的話!!!

緊接著,我們再來看看狀態:

CTRL+C:傳送SIGINT訊號給前臺程序組中的所有程序。常用於終止正在執行的程式,強制中斷程式的執行

CTRL+Z:傳送SIGTSTP訊號給前臺程序組中的所有程序,常用於掛起一個程序,是將任務中斷,但是此任務並沒有結束,它仍然在程序中他只是維持掛起的狀態,使用者可以使用fg/bg操作繼續前臺或後臺的任務,fg命令重新啟動前臺被中斷的任務,bg命令把被中斷的任務放在後臺執行

可知,如果我們呼叫kill的話,那麼我們還能觀察到對等的狀態,如果我們呼叫CTRL + C的話,那麼我們的整個服務端

程式都被中斷

總之:上面說了這麼多的原因,就是說,一端A呼叫close退出的話,會發送FIN分節給

對端B,但是對於B接收到A的分節之後,並不能保證A端的程序是不是已經消失,,,

因為對方呼叫close,並不意味著對方的程序會消失,,,當然,上面我們是通過kill或

者CTRL + C來確保的,如果這時B端再呼叫write,發現A端不存在,那麼TCP協議棧會

傳送一個RST分節(連線重置的TCP端),對於當前的全雙工管道而言,如果再次調

用write函式的話,那麼就會

產生SIGPIPE訊號中斷。。。。。。。。。。

相關推薦

TCP狀態轉化過程11狀態以及TIME_WAIT狀態

TCP中的三次握手,四次揮手是我們所熟知的,可是,我們熟悉裡面的各種狀態嗎??? (SYN_SENT,   ESTABLISHED,    CLOSE_WAIT.............),試問一句,我們瞭解裡面的狀態轉化嗎??? 1,大家先看一個簡單的通訊圖(圖片轉載

Zookeeper常用命令列命令類unix命令以及 Stat狀態說明

1 常見命令(類unix命令) 命令基本語法 功能描述 help 顯示所有操作命令 ls path [watch] 使用 ls 命令來檢視當前znode中所包含的內容

HTTP狀態碼大全轉自wiki

成對 節點 而是 沒有 redirect port multiple 許可 sta 1xx消息 這一類型的狀態碼,代表請求已被接受,需要繼續處理。這類響應是臨時響應,只包含狀態行和某些可選的響應頭信息,並以空行結束。由於HTTP/1.0協議中沒有定義任何1xx狀態碼,所以除

Nginx輸出基本狀態信息Ngx_http_stub_module模塊

web;nginx;linux輸出Nginx基本狀態信息(Ngx_http_stub_status_module)官方文檔:http://nginx.org/en/docs/http/ngx_http_status_module.html官方定義:The ngx_http_stub_status_module

設計模式 十七 狀態模式State物件行為型

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

TCP/IP學習筆記11-tcp互動資料流,成塊資料流

        目前建立在TCP協議上的網路協議特別多,有telnet,ssh,有ftp,有http等等。這些協議又可以根據資料吞吐量來大致分成兩大類:      

HTTP狀態碼一覽表HTTP Status Code

英文版: 100:Continue 101:Switching Protocols 102:Processing 200:OK 201:Created 202:Accepted 203:Non-Authoriative Information 204:No Content 205:Reset Content

在KVM設定TLS證書認證TCP和VNC連線填坑版

本文是一篇散文 今天我們就來說一下KVM的安全配置 KVM的安全實現有很多型別 比如用SSH來連線KVM管理器 但是SSH這個方法有個不好的地方就是沒法對我們的VNC加密 或者就是我們這裡的TLS配置 既然涉及到了TLS肯定離不開證書 我們就先從證

狀態模式State物件行為型

1.概述 在軟體開發過程中,應用程式可能會根據不同的情況作出不同的處理。最直接的解決方案是將這些所有可能發生的情況全都考慮到。然後使用if... ellse語句來做狀態判斷來進行不同情況的處理。但是對複雜狀態的判斷就顯得“力不從心了”。隨著增加新的狀態或者修改一個狀體(if else(或sw

hihocoder-1048 狀態壓縮·二狀壓DP

小Ho的觀察力一向不錯,這不,他很快便發現了M的取值範圍只可能為3、4、5三種情況,但是這一發現並沒有能夠給他減輕多少煩惱。 雖然在過去一段時間的訓練下,小Ho很快就意識到這道題目可能仍然是需要使用動態規劃進行解決,但是他苦思冥想也沒有能夠想到很好的狀態定義方式:“如果我每次列舉一塊蛋糕的放置位置,那麼我就

設計模式 十七 狀態模式State物件行為型

                1.概述在軟體開發過程中,應用程式可能會根據不同的情況作出不同的處理。最直接的解決方案是將這些所有可能發生的情況全都考慮到。然後使用if... ellse語句來做狀態判斷來進行不同情況的處理。但是對複雜狀態的判斷就顯得“力不從心了”。隨著增加新的狀態或者修改一個狀體(if el

iPhone X XS XR XSMAX如何根據狀態列上的圖示 獲取裝置的聯網狀態不是單個應用的

在iPhone X 上通過狀態列獲取聯網狀態使用下面的程式碼直接閃退 - (BOOL)networkingStatesFromStatebar { UIApplication *app = [UIApplication sharedApplication];

Vuex 在工程化的使用以及state狀態屬性的使用筆記

Vuex是什麼? 引入官方提供的解釋,vuex 是專門為 vue.js 設計的一套 狀態管理模式 。什麼是狀態管理模式?說白了就是資料的集中管理。我們在使用 vue.js 時所用到的資料全部抽取出來放在一個state物件下,這樣我們在任何元件內都可以訪

TCP/IP通訊過程以傳送電子郵件為例

1.應用程式處理 (1)A使用者啟動郵件應用程式,填寫收件人郵箱和傳送內容,點選“傳送”,開始TCP/IP通訊; (2)應用程式對傳送的內容進行編碼處理,這一過程相當於OSI的表示層功能; (3)由A使用者所使用的郵件軟體決定何時建立通訊連

【POJ2411】Mondriaan's Dream-狀態壓縮DP插頭DP?

題目大意:求用1*2的骨牌完美覆蓋h*w的棋盤的方法數。 做法:這道題絕對是經典題啊,久仰大名......關於輪廓線和插頭的思想可以看cdq大大的論文:點這裡。但這題不用搞那麼麻煩,因為骨牌之間相互

TCP/IP學習筆記11——廣播和多播

1、引言 廣播和多播僅應用於 UDP,它們對需將報文同時傳往多個接收者的應用來說十分重要。TCP是一個面向連線的協議,它意味著分別運行於兩主機(由 IP地址確定)內的兩程序(由埠號確定)間存在一條連線。 考慮包含多個主機的共享通道網路如乙太網。每個乙太網幀包

TCP狀態圖的理解以及TIME_WAIT狀態的作用

TCP/IP狀態圖 以及 TIME_WAIT作用 在TCP/IP狀態圖中,有很多種的狀態,它們之間有的是可以互相轉換的,也就是說,從一種狀態轉到另一種狀態,但是這種轉換不是隨便傳送的,是要滿足一定的條件。TCP/IP狀態圖看起來更像是自動機。下圖即為TCP/IP狀態。 由上圖可以看出,一共有11種

Linux下apache日誌按日期存放分析與狀態檢視方法

一、apache日誌按日期記錄 在apache的配置檔案中找到 ErrorLog logs/error_log CustomLog logs/access_log common Linux系統配

使用Charles3.11.2過程附加下載Mac

做iOS苦於沒有UI素材和JSON或XML資料資源等,我們可以嘗試用Charles來進行其他App捉包進行獲取想要的素材。(真心想做出自己理想的app不是抄襲而是藉助來學習) 安裝好javaforosx 之後再安裝Charles-proxy-3.11.2 複製charl

【UE4】【C++】列舉類對於不同狀態顯示不同的顏色準心C++設定狀態,藍圖設定顏色UI顏色繫結

官方對列舉的用法https://wiki.unrealengine.com/Enums_For_Both_C%2B%2B_and_BP寫在UClass上面、#include下面UENUM() enum class EFiringState :uint8 {        //