主動斷開socket鏈接_TCP連接與斷開詳解(socket通信)

http://blog.csdn.net/Ctrl_qun/article/details/52518479

一、TCP數據報結構以及三次握手

TCP(Transmission Control Protocol,傳輸控制協議)是一種面向連接的、可靠的、基于字節流的通信協議,數據在傳輸前要建立連接,傳輸完畢后還要斷開連接。

客戶端在收發數據前要使用 connect() 函數和服務器建立連接。建立連接的目的是保證IP地址、端口、物理鏈路等正確無誤,為數據的傳輸開辟通道。

TCP建立連接時要傳輸三個數據包,俗稱三次握手(Three-way Handshaking)。可以形象的比喻為下面的對話:

[Shake 1] 套接字A:“你好,套接字B,我這里有數據要傳送給你,建立連接吧。”

[Shake 2] 套接字B:“好的,我這邊已準備就緒。”

[Shake 3] 套接字A:“謝謝你受理我的請求。”

TCP數據報結構

我們先來看一下TCP數據報的結構:

帶陰影的幾個字段需要重點說明一下:

1) 序號:Seq(Sequence Number)序號占32位,用來標識從計算機A發送到計算機B的數據包的序號,計算機發送數據時對此進行標記。

2)?確認號:Ack(Acknowledge Number)確認號占32位,客戶端和服務器端都可以發送,Ack = Seq + 1。

3)?標志位:每個標志位占用1Bit,共有6個,分別為 URG、ACK、PSH、RST、SYN、FIN,具體含義如下:

URG:緊急指針(urgent pointer)有效。

ACK:確認序號有效。

PSH:接收方應該盡快將這個報文交給應用層。

RST:重置連接。

SYN:建立一個新連接。

FIN:斷開一個連接。

對英文字母縮寫的總結:Seq 是?Sequence 的縮寫,表示序列;Ack(ACK) 是?Acknowledge 的縮寫,表示確認;SYN 是?Synchronous 的縮寫,愿意是“同步的”,這里表示建立同步連接;FIN 是 Finish 的縮寫,表示完成。

連接的建立(三次握手)

使用 connect() 建立連接時,客戶端和服務器端會相互發送三個數據包,請看下圖:

客戶端調用 socket() 函數創建套接字后,因為沒有建立連接,所以套接字處于CLOSED狀態;服務器端調用 listen() 函數后,套接字進入LISTEN狀態,開始監聽客戶端請求。

這個時候,客戶端開始發起請求:

1) 當客戶端調用 connect() 函數后,TCP協議會組建一個數據包,并設置 SYN 標志位,表示該數據包是用來建立同步連接的。同時生成一個隨機數字 1000,填充“序號(Seq)”字段,表示該數據包的序號。完成這些工作,開始向服務器端發送數據包,客戶端就進入了SYN-SEND狀態。

2) 服務器端收到數據包,檢測到已經設置了 SYN 標志位,就知道這是客戶端發來的建立連接的“請求包”。服務器端也會組建一個數據包,并設置 SYN 和 ACK 標志位,SYN 表示該數據包用來建立連接,ACK 用來確認收到了剛才客戶端發送的數據包。

服務器生成一個隨機數 2000,填充“序號(Seq)”字段。2000 和客戶端數據包沒有關系。

服務器將客戶端數據包序號(1000)加1,得到1001,并用這個數字填充“確認號(Ack)”字段。

服務器將數據包發出,進入SYN-RECV狀態。

3) 客戶端收到數據包,檢測到已經設置了 SYN 和 ACK 標志位,就知道這是服務器發來的“確認包”。客戶端會檢測“確認號(Ack)”字段,看它的值是否為 1000+1,如果是就說明連接建立成功。

接下來,客戶端會繼續組建數據包,并設置 ACK 標志位,表示客戶端正確接收了服務器發來的“確認包”。同時,將剛才服務器發來的數據包序號(2000)加1,得到 2001,并用這個數字來填充“確認號(Ack)”字段。

客戶端將數據包發出,進入ESTABLISED狀態,表示連接已經成功建立。

4) 服務器端收到數據包,檢測到已經設置了 ACK 標志位,就知道這是客戶端發來的“確認包”。服務器會檢測“確認號(Ack)”字段,看它的值是否為 2000+1,如果是就說明連接建立成功,服務器進入ESTABLISED狀態。

至此,客戶端和服務器都進入了ESTABLISED狀態,連接建立成功,接下來就可以收發數據了。

最后的說明

三次握手的關鍵是要確認對方收到了自己的數據包,這個目標就是通過“確認號(Ack)”字段實現的。計算機會記錄下自己發送的數據包序號 Seq,待收到對方的數據包后,檢測“確認號(Ack)”字段,看Ack = Seq + 1是否成立,如果成立說明對方正確收到了自己的數據包。

二、TCP數據的傳輸過程

建立連接后,兩臺主機就可以相互傳輸數據了。如下圖所示:

圖1:TCP 套接字的數據交換過程

上圖給出了主機A分2次(分2個數據包)向主機B傳遞200字節的過程。首先,主機A通過1個數據包發送100個字節的數據,數據包的 Seq 號設置為 1200。主機B為了確認這一點,向主機A發送 ACK 包,并將 Ack 號設置為 1301。

為了保證數據準確到達,目標機器在收到數據包(包括SYN包、FIN包、普通數據包等)包后必須立即回傳ACK包,這樣發送方才能確認數據傳輸成功。

此時 Ack 號為 1301 而不是 1201,原因在于 Ack 號的增量為傳輸的數據字節數。假設每次 Ack 號不加傳輸的字節數,這樣雖然可以確認數據包的傳輸,但無法明確100字節全部正確傳遞還是丟失了一部分,比如只傳遞了80字節。因此按如下的公式確認 Ack 號:

Ack號 = Seq號 + 傳遞的字節數 + 1

與三次握手協議相同,最后加 1 是為了告訴對方要傳遞的 Seq 號。

下面分析傳輸過程中數據包丟失的情況,如下圖所示:

圖2:TCP套接字數據傳輸過程中發生錯誤

上圖表示通過 Seq 1301 數據包向主機B傳遞100字節的數據,但中間發生了錯誤,主機B未收到。經過一段時間后,主機A仍未收到對于 Seq 1301 的ACK確認,因此嘗試重傳數據。

為了完成數據包的重傳,TCP套接字每次發送數據包時都會啟動定時器,如果在一定時間內沒有收到目標機器傳回的 ACK 包,那么定時器超時,數據包會重傳。

上圖演示的是數據包丟失的情況,也會有 ACK 包丟失的情況,一樣會重傳。

重傳超時時間(RTO, Retransmission Time Out)

這個值太大了會導致不必要的等待,太小會導致不必要的重傳,理論上最好是網絡 RTT 時間,但又受制于網絡距離與瞬態時延變化,所以實際上使用自適應的動態算法(例如 Jacobson 算法和 Karn 算法等)來確定超時時間。

往返時間(RTT,Round-Trip Time)表示從發送端發送數據開始,到發送端收到來自接收端的 ACK 確認包(接收端收到數據后便立即確認),總共經歷的時延。

重傳次數

TCP數據包重傳次數根據系統設置的不同而有所區別。有些系統,一個數據包只會被重傳3次,如果重傳3次后還未收到該數據包的 ACK 確認,就不再嘗試重傳。但有些要求很高的業務系統,會不斷地重傳丟失的數據包,以盡最大可能保證業務數據的正常交互。

三、TCP四次握手斷開連接

建立連接非常重要,它是數據正確傳輸的前提;斷開連接同樣重要,它讓計算機釋放不再使用的資源。如果連接不能正常斷開,不僅會造成數據傳輸錯誤,還會導致套接字不能關閉,持續占用資源,如果并發量高,服務器壓力堪憂。

建立連接需要三次握手,斷開連接需要四次握手,可以形象的比喻為下面的對話:

[Shake 1] 套接字A:“任務處理完畢,我希望斷開連接。”

[Shake 2] 套接字B:“哦,是嗎?請稍等,我準備一下。”

等待片刻后……

[Shake 3] 套接字B:“我準備好了,可以斷開連接了。”

[Shake 4] 套接字A:“好的,謝謝合作。”

下圖演示了客戶端主動斷開連接的場景:

建立連接后,客戶端和服務器都處于ESTABLISED狀態。這時,客戶端發起斷開連接的請求:

1) 客戶端調用 close() 函數后,向服務器發送 FIN 數據包,進入FIN_WAIT_1狀態。FIN 是 Finish 的縮寫,表示完成任務需要斷開連接。

2) 服務器收到數據包后,檢測到設置了 FIN 標志位,知道要斷開連接,于是向客戶端發送“確認包”,進入CLOSE_WAIT狀態。

注意:服務器收到請求后并不是立即斷開連接,而是先向客戶端發送“確認包”,告訴它我知道了,我需要準備一下才能斷開連接。

3) 客戶端收到“確認包”后進入FIN_WAIT_2狀態,等待服務器準備完畢后再次發送數據包。

4) 等待片刻后,服務器準備完畢,可以斷開連接,于是再主動向客戶端發送 FIN 包,告訴它我準備好了,斷開連接吧。然后進入LAST_ACK狀態。

5) 客戶端收到服務器的 FIN 包后,再向服務器發送 ACK 包,告訴它你斷開連接吧。然后進入TIME_WAIT狀態。

6) 服務器收到客戶端的 ACK 包后,就斷開連接,關閉套接字,進入CLOSED狀態。

關于 TIME_WAIT 狀態的說明

客戶端最后一次發送 ACK包后進入 TIME_WAIT 狀態,而不是直接進入 CLOSED 狀態關閉連接,這是為什么呢?

TCP 是面向連接的傳輸方式,必須保證數據能夠正確到達目標機器,不能丟失或出錯,而網絡是不穩定的,隨時可能會毀壞數據,所以機器A每次向機器B發送數據包后,都要求機器B”確認“,回傳ACK包,告訴機器A我收到了,這樣機器A才能知道數據傳送成功了。如果機器B沒有回傳ACK包,機器A會重新發送,直到機器B回傳ACK包。

客戶端最后一次向服務器回傳ACK包時,有可能會因為網絡問題導致服務器收不到,服務器會再次發送 FIN 包,如果這時客戶端完全關閉了連接,那么服務器無論如何也收不到ACK包了,所以客戶端需要等待片刻、確認對方收到ACK包后才能進入CLOSED狀態。那么,要等待多久呢?

數據包在網絡中是有生存時間的,超過這個時間還未到達目標主機就會被丟棄,并通知源主機。這稱為報文最大生存時間(MSL,Maximum Segment Lifetime)。TIME_WAIT 要等待 2MSL 才會進入 CLOSED 狀態。ACK 包到達服務器需要 MSL 時間,服務器重傳 FIN 包也需要 MSL 時間,2MSL 是數據包往返的最大時間,如果 2MSL 后還未收到服務器重傳的 FIN 包,就說明服務器已經收到了 ACK 包。

四、優雅的斷開連接--shutdown()

調用 close()/closesocket() 函數意味著完全斷開連接,即不能發送數據也不能接收數據,這種“生硬”的方式有時候會顯得不太“優雅”。

圖1:close()/closesocket() 斷開連接

上圖演示了兩臺正在進行雙向通信的主機。主機A發送完數據后,單方面調用?close()/closesocket() 斷開連接,之后主機A、B都不能再接受對方傳輸的數據。實際上,是完全無法調用與數據收發有關的函數。

一般情況下這不會有問題,但有些特殊時刻,需要只斷開一條數據傳輸通道,而保留另一條。

使用 shutdown() 函數可以達到這個目的,它的原型為:

int?shutdown(int?sock,?int?howto);??//Linux

int?shutdown(SOCKET?s,?int?howto);??//Windows

sock 為需要斷開的套接字,howto 為斷開方式。

howto 在 Linux 下有以下取值:

SHUT_RD:斷開輸入流。套接字無法接收數據(即使輸入緩沖區收到數據也被抹去),無法調用輸入相關函數。

SHUT_WR:斷開輸出流。套接字無法發送數據,但如果輸出緩沖區中還有未傳輸的數據,則將傳遞到目標主機。

SHUT_RDWR:同時斷開 I/O 流。相當于分兩次調用 shutdown(),其中一次以 SHUT_RD 為參數,另一次以 SHUT_WR 為參數。

howto 在 Windows 下有以下取值:

SD_RECEIVE:關閉接收操作,也就是斷開輸入流。

SD_SEND:關閉發送操作,也就是斷開輸出流。

SD_BOTH:同時關閉接收和發送操作。

至于什么時候需要調用 shutdown() 函數,下節我們會以文件傳輸為例進行講解。

close()/closesocket()和shutdown()的區別

確切地說,close() / closesocket() 用來關閉套接字,將套接字描述符(或句柄)從內存清除,之后再也不能使用該套接字,與C語言中的 fclose() 類似。應用程序關閉套接字后,與該套接字相關的連接和緩存也失去了意義,TCP協議會自動觸發關閉連接的操作。

shutdown() 用來關閉連接,而不是套接字,不管調用多少次 shutdown(),套接字依然存在,直到調用 close() / closesocket() 將套接字從內存清除。

調用 close()/closesocket() 關閉套接字時,或調用 shutdown() 關閉輸出流時,都會向對方發送 FIN 包。FIN 包表示數據傳輸完畢,計算機收到 FIN 包就知道不會再有數據傳送過來了。

默認情況下,close()/closesocket() 會立即向網絡中發送FIN包,不管輸出緩沖區中是否還有數據,而shutdown() 會等輸出緩沖區中的數據傳輸完畢再發送FIN包。也就意味著,調用 close()/closesocket() 將丟失輸出緩沖區中的數據,而調用 shutdown() 不會。

五、socket文件傳輸功能的實現

我們來完成 socket 文件傳輸程序,這是一個非常實用的例子。要實現的功能為:client 從 server 下載一個文件并保存到本地。

編寫這個程序需要注意兩個問題:

1) 文件大小不確定,有可能比緩沖區大很多,調用一次 write()/send() 函數不能完成文件內容的發送。接收數據時也會遇到同樣的情況。

要解決這個問題,可以使用 while 循環,例如:

//Server?代碼

int?nCount;

while(?(nCount?=?fread(buffer,?1,?BUF_SIZE,?fp))?>?0?){

send(sock,?buffer,?nCount,?0);

}

//Client?代碼

int?nCount;

while(?(nCount?=?recv(clntSock,?buffer,?BUF_SIZE,?0))?>?0?){

fwrite(buffer,?nCount,?1,?fp);

}

對于 Server 端的代碼,當讀取到文件末尾,fread() 會返回 0,結束循環。

對于 Client 端代碼,有一個關鍵的問題,就是文件傳輸完畢后讓 recv() 返回 0,結束 while 循環。

注意:讀取完緩沖區中的數據 recv() 并不會返回 0,而是被阻塞,直到緩沖區中再次有數據。

2) Client 端如何判斷文件接收完畢,也就是上面提到的問題——何時結束 while 循環。

最簡單的結束 while 循環的方法當然是文件接收完畢后讓 recv() 函數返回 0,那么,如何讓 recv() 返回 0 呢?recv() 返回 0 的唯一時機就是收到FIN包時。

FIN 包表示數據傳輸完畢,計算機收到 FIN 包后就知道對方不會再向自己傳輸數據,當調用 read()/recv() 函數時,如果緩沖區中沒有數據,就會返回 0,表示讀到了”socket文件的末尾“。

這里我們調用 shutdown() 來發送FIN包:server 端直接調用 close()/closesocket() 會使輸出緩沖區中的數據失效,文件內容很有可能沒有傳輸完畢連接就斷開了,而調用 shutdown() 會等待輸出緩沖區中的數據傳輸完畢。

本節以Windows為例演示文件傳輸功能,Linux與此類似,不再贅述。請看下面完整的代碼。

服務器端 server.cpp:

#include?

#include?

#include?

#pragma?comment?(lib,?"ws2_32.lib")??//加載?ws2_32.dll

#define?BUF_SIZE?1024

int?main(){

//先檢查文件是否存在

char?*filename?=?"D:\\send.avi";??//文件名

FILE?*fp?=?fopen(filename,?"rb");??//以二進制方式打開文件

if(fp?==?NULL){

printf("Cannot?open?file,?press?any?key?to?exit!\n");

system("pause");

exit(0);

}

WSADATA?wsaData;

WSAStartup(?MAKEWORD(2,?2),?&wsaData);

SOCKET?servSock?=?socket(AF_INET,?SOCK_STREAM,?0);

sockaddr_in?sockAddr;

memset(&sockAddr,?0,?sizeof(sockAddr));

sockAddr.sin_family?=?PF_INET;

sockAddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");

sockAddr.sin_port?=?htons(1234);

bind(servSock,?(SOCKADDR*)&sockAddr,?sizeof(SOCKADDR));

listen(servSock,?20);

SOCKADDR?clntAddr;

int?nSize?=?sizeof(SOCKADDR);

SOCKET?clntSock?=?accept(servSock,?(SOCKADDR*)&clntAddr,?&nSize);

//循環發送數據,直到文件結尾

char?buffer[BUF_SIZE]?=?{0};??//緩沖區

int?nCount;

while(?(nCount?=?fread(buffer,?1,?BUF_SIZE,?fp))?>?0?){

send(clntSock,?buffer,?nCount,?0);

}

shutdown(clntSock,?SD_SEND);??//文件讀取完畢,斷開輸出流,向客戶端發送FIN包

recv(clntSock,?buffer,?BUF_SIZE,?0);??//阻塞,等待客戶端接收完畢

fclose(fp);

closesocket(clntSock);

closesocket(servSock);

WSACleanup();

system("pause");

return?0;

}

客戶端代碼:

#include?

#include?

#include?

#pragma?comment(lib,?"ws2_32.lib")

#define?BUF_SIZE?1024

int?main(){

//先輸入文件名,看文件是否能創建成功

char?filename[100]?=?{0};??//文件名

printf("Input?filename?to?save:?");

gets(filename);

FILE?*fp?=?fopen(filename,?"wb");??//以二進制方式打開(創建)文件

if(fp?==?NULL){

printf("Cannot?open?file,?press?any?key?to?exit!\n");

system("pause");

exit(0);

}

WSADATA?wsaData;

WSAStartup(MAKEWORD(2,?2),?&wsaData);

SOCKET?sock?=?socket(PF_INET,?SOCK_STREAM,?IPPROTO_TCP);

sockaddr_in?sockAddr;

memset(&sockAddr,?0,?sizeof(sockAddr));

sockAddr.sin_family?=?PF_INET;

sockAddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");

sockAddr.sin_port?=?htons(1234);

connect(sock,?(SOCKADDR*)&sockAddr,?sizeof(SOCKADDR));

//循環接收數據,直到文件傳輸完畢

char?buffer[BUF_SIZE]?=?{0};??//文件緩沖區

int?nCount;

while(?(nCount?=?recv(sock,?buffer,?BUF_SIZE,?0))?>?0?){

fwrite(buffer,?nCount,?1,?fp);

}

puts("File?transfer?success!");

//文件接收完畢后直接關閉套接字,無需調用shutdown()

fclose(fp);

closesocket(sock);

WSACleanup();

system("pause");

return?0;

}

在D盤中準備好send.avi文件,先運行 server,再運行 client:

Input filename to save: D:\\recv.avi↙

//稍等片刻后

File transfer success!

打開D盤就可以看到 recv.avi,大小和 send.avi 相同,可以正常播放。

注意 server.cpp 第42行代碼,recv() 并沒有接收到 client 端的數據,當 client 端調用 closesocket() 后,server 端會收到FIN包,recv() 就會返回,后面的代碼繼續執行。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/534112.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/534112.shtml
英文地址,請注明出處:http://en.pswp.cn/news/534112.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大整數算術求值 c語言 棧,用C語言實現 多位整數的四則運算,用棧,例如56*(12+20)-102/2...

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓gets(szExpression);// 中綴表達式轉后綴表達式&#xff0c;結果保存在expression中for (int i 0; i < strlen(szExpression); i){if (isspace(szExpression[i])) // 空白字符{if (bFindBegin){expression[num].type 1;expres…

java可視化壓縮_WEB可視化技術發展

EverCraft一直在關注Web可視化技術的發展&#xff0c;本文對國外一篇感覺很不錯的綜述性文章進行翻譯&#xff0c;供這一領域的愛好者相互學習。這篇paper的信息為&#xff1a;“Mwalongo, F., et al., State-of-the-Art Report in Web-based Visualization. COMPUTER GRAPHICS…

thumbdata4刪除后果_安卓手機上巨大的.thumbdata4圖片預讀緩存清理方法

以下是目前找到比較有效的幫 .thumbdata4-文件瘦身的好方法.下面的一大堆廢話的核心就是進手機設置>應用程序>顯示系統程序>媒體存儲器>存儲>清除數據/緩存.重啟后會發現thumbdata還會出現但是沒有數GB那么大了.How do I Reset the AndroidMedia Scan Database?…

android自定義alertdialog不現實輸入法,自定義的dialog中的EditText無法彈出輸入法解決方案...

1.解決無法彈出輸入法&#xff1a;在show()方法調用之前&#xff0c;用dialog.setView(new EditText(context))添加一個空的EditText&#xff0c;由于是自定義的AlertDialog&#xff0c;有我們指定的布局&#xff0c;所以設置這個不會影響我們的功能&#xff0c;這樣就可以彈出…

python爬取微博內容_請問該如何通過python調用新浪微博的API來爬取數據?

1&#xff1a;安裝python(這個不多說啦) 2&#xff1a;下載新浪微博SDK的python包&#xff0c;解壓為weibopy目錄 3&#xff1a;申請AppKey&#xff0c; 流程&#xff1a; 1&#xff1a;通過oAuth認證 按我的理解簡化如下&#xff1a; 用戶在新浪微博給的頁面輸入賬號密碼&…

android 保活方案_Android 后臺保活手段總結 (上篇)

Android 后臺保活手段總結 (上篇)由于眾所周知的限制&#xff0c;在國內無法使用GCM推送服務&#xff0c;想要自己搭建推送服務的話&#xff0c;有兩個繞不開的技術點&#xff0c;一個是TCP長連的保活&#xff0c;另一個就是后臺進程的保活。雖然看起來是老生常談的問題&#x…

linux修改棧指針x86,為什么x86-64 Linux系統調用會修改RCX,這個值意味著什么?

我正在嘗試使用sys_brk syscall在linux中分配一些內存.這是我嘗試過的&#xff1a;BYTES_TO_ALLOCATE equ 0x08section .textglobal _start_start:mov rax, 12mov rdi, BYTES_TO_ALLOCATEsyscallmov rax, 60syscall根據linux調用約定,我希望返回值在rax寄存器中(指向已分配內存…

wordpress phpmyadmin_西部數碼使用指南:虛擬主機WordPress部署SSL注意事項

版權歸西部數碼所有&#xff0c;原文鏈接&#xff1a;https://www.west.cn/faq/list.asp?unid2068注意事項&#xff1a;1.如果您的主題/插件使用絕對地址調用了http請求可能會導致網站打開會亂碼&#xff0c;或不能有綠鎖標識&#xff0c;需要聯系程序提供商將所有http請求修改…

android html轉pdf工具,android – 使用iText庫將html轉換為pdf時未應用hr的內聯CSS

我是.NET開發人員,因此代碼在C#中.但是你應該能夠輕松翻譯以下內容.iText是一個PDF優先的庫,[X] HTML解析非常復雜,因此在這方面并不完整.每當解析[X] HTML并且事情不按預期的方式進行特定標記時,您應遵循的基本步驟是&#xff1a;>驗證XML Worker支持標記&#xff1a;Tags …

python 小說爬蟲_從零開始寫Python爬蟲 --- 1.7 爬蟲實踐: 排行榜小說批量下載

從零開始寫Python爬蟲 --- 1.7 爬蟲實踐&#xff1a; 排行榜小說批量下載Ehco 5 個月前 本來只是準備做一個爬起點小說名字的爬蟲&#xff0c;后來想了一下&#xff0c;為啥不順便把小說的內容也爬下來呢&#xff1f;于是我就寫了這個爬蟲&#xff0c;他爬下了各類小說排行榜上…

java 某個字符在字符串中出現的所有位置_Java面試常考核心概念

這篇文章專注于Java基礎知識&#xff0c;不涉及List、Map、多線程、鎖相關的內容&#xff0c;需要的可以查看我的其他博客hofes blog?hhf443.github.ioJDK&JRE&JVMJDK&#xff08;Java Development Kit&#xff09;是針對 Java 開發員的產品&#xff0c;是整個 Java 的…

lan交換和無線教師手冊_簡單幾步,無線路由器變交換機

當原來的路由器lan口不夠用&#xff0c;可以加一個交換機擴展lan口數量&#xff0c;如果需要增加的lan口數量不超過3個可以考慮找臺不用的無線路由器當交換機用。另外&#xff0c;隨著交換機更新家中都有舊無線路由器閑置&#xff0c;完全可以再次利用。下面看一下&#xff0c;…

Linux fast open,Linux內核3.7 TCP Fast Open驗證實例

Linux內核在3.6和3.7合入了TCP Fast Open特性&#xff0c;在3.7.3版本上驗證了一下&#xff0c;I did it!以下是C語言實例()&#xff1a;server端代碼&#xff1a;#include /* See NOTES */#include#include#includeint main(){int portno 5060;socklen_t clilen;char buffer[…

vue 怎么全局到入常量_Vue 中如何定義全局的變量和常量(轉)

17.6k 次閱讀 讀完需要 10 分鐘7Vue 中如何定義全局的變量和常量我想要定義一個變量, 在項目的任何地方都可以訪問到, 不需要每一次使用的時候, 都引入.嘗試1:創建 global.js 并且在其中定義let a 10;在入口文件中引入 global.jsimport ./global.js在項目中使用:a// 報錯發…

revit找不到附加模塊程序集_TensorFlow基礎知識——常用模塊(一)

1本節簡述對于開展深度學習開發的目標而言&#xff0c;我們需要掌握的除了必要的深度學習理論基礎、必要的開發依賴庫基礎知識、基本的開發套路之外&#xff0c;我們還需要掌握它常見的外圍小幫手都有哪些。這些小幫手就是深度學習依賴庫中的其他并不是核心的模塊&#xff0c;但…

android搭建opencv開發環境,Android Studio搭建opencv開發環境

文章不配圖片&#xff0c;閱讀需要有Android開發基礎并熟悉Android Studio。一、搭建基于Java開發環境以下內容介紹如何搭建基于Java jni的opencv開發環境。1、準備工作從opencv官網下載Android平臺開發sdk并解壓&#xff0c;假設解壓后文件夾名為opencv-4.3.0-android-sdk。(此…

99 網絡編程_網絡工程師技能圖譜,看看你會多少技能

技術推動了時代變革&#xff0c;互聯網則加速了這場變革。在蓬勃發展的互聯網浪潮下&#xff0c;網絡作為基礎設施的關鍵紐帶保障著網路流量的順利流通&#xff0c;維持著賽博世界的繁榮。而在這繁榮之下&#xff0c;生存著這樣一個群體——網絡工程獅&#xff0c;為網絡紐帶保…

python 3.8.0安卓_Python for Mac v3.8.0 官方最新版

Python for Mac是一款全新推出的編程工具&#xff0c;所有 python.org macOS 安裝程序都附帶了 OpenSSL 的內置副本。此外&#xff0c;還有一個針對 macOS 10.9 的新增安裝程序變體&#xff0c;其中包含 Tcl / Tk 8.6的內置版本&#xff0c;有需要的朋友快來下載試試吧!Python …

線程join_Java 并發編程:線程間的協作(wait/notify/sleep/yield/join)

點擊上方“Coder編程”&#xff0c;選擇“置頂公眾號”技術文章第一時間送達&#xff01;并發編程.png每天進步一點&#xff0c;不做curd工程師與Api調用工程師 歡迎訪問個人博客網站&#xff1a;https://www.coder-programming.cn/ 作者&#xff1a;liuxiaopeng | http://www…

4位先行進位電路 logisim_你真的了解74系列集成電路嗎?讓我幫你總結一下

74系列集成電路大致可分為6大類&#xff1a;74(標準型)74LS(低功耗肖特基)74S(肖特基)74ALS(先進低功耗肖特基)74AS(先進肖特基)74F(高速)HC為COMS工作電平&#xff1b;HCT為TTL工作電平&#xff0c;可與74LS系列互換使用HCU適用于無緩沖級的CMOS電路。這9種74系列產品&#xf…