uc_15_TCP協議

1? TCP協議

? ? ? ? TCP提供客戶機與服務器的鏈接。一個完整TCP通信過程需要經歷三個階段

? ? ? ? 1)首先,客戶機必須建立與服務器的連接,所謂虛電路

? ? ? ? 2)然后,憑借已建立好的連接,通信雙方相互交換數據

? ? ? ? 3)最后,客戶機與服務器雙雙終止連接,結束通信過程

? ? ? ? TCP保證數據傳輸的可靠性(超時重傳、反向確認):

? ? ? ? TCP的協議棧底層在向另一端發送數據時,會要求對方在一個給定的時間窗口內返回確認。如果超過了這個時間窗口仍沒有收到確認,則TCP會重傳數據并等待更長的時間。只有在數次重傳均告失敗以后,TCP才會最終放棄。TCP含有用于動態估算數據往返時間(Round-Trip Time, RTT)的算法,因此它知道等待一個確認需要多長時間。

? ? ? ? TCP保證數據傳輸的有序性

? ? ? ? TCP的協議棧底層在向另一端發送數據時,會為所發送數據的每個字節指定一個序列號。即使這些數據字節沒有能夠按照發送時的順序到達接收方,接收方的TCP也可以根據它們的序列號重新排序,再把最后的結果交給應用程序。

? ? ? ? TCP是全雙工的:

? ? ? ? 在給定的連接上,應用程序在任何時候都既可以發送數據也可以接收數據。因此,TCP必須跟蹤每個方向上數據流的狀態信息,如序列號和通告窗口的大小。

1.1??三次握手(建立連接)

?????????????????????????

? ? ? ? ? ? ? ? ? ? ????????????????? ? ?三次握手?????????????????????????????????????????????????? ? ? ? ?交換數據

? ? ? ? 1)客戶機的TCP協議棧向服務器發送一個SYN分節(SYN比特位是1),告知對方自己將在連接中發送數據的初始序列號,稱為主動打開。

? ? ? ? 2)服務器的TCP協議棧向客戶機發送一個單個分節,其中不僅包括對客戶機SYN分節的ACK應答,還包含服務器自己的SYN分節(ACK和SYN比特位均是1),以告知對方自己在同一連接中發送數據的初始序列號。

? ? ? ? 3)客戶機的TCP協議棧向服務器返回ACK應答,以表示對服務器所發SYN的確認。
?

? ? ? ? 交換數據

? ? ? ? - 一旦連接建立,客戶機即可構造請求包,并發往服務器。服務器接收并處理來自客戶機的請求包,構造響應包。

? ? ? ? - 服務器向客戶機發送響應包,同時捎帶對客戶機請求包的ACK應答(反向確認)。

? ? ? ? - 客戶機接收來自服務器的響應包,同時向對方發送ACK應答(反向確認)。

1.2? 四次揮手(關閉連接)

? ? ? ???????????????????????????????????? ? ? ? ? ? ? ?

????????1)客戶機或者服務器主動關閉連接,TCP協議向對方發送FIN分節,表示數據通信結束。如果此時尚有數據滯留于發送緩沖區中,則FIN分節跟在所有未發送數據之后。

????????2)接收到FIN分節的另一端執行被動關閉,一方面通過TCP協議棧向對方發送ACK應答,另一方面向應用程序傳遞文件結束符。

????????3)一段時間后,方才接收到FIN分節的進程關閉自己的鏈接,同時通過TCP協議棧向對方發送FIN分節。

????????4)對方在收到FIN分節后發送ACK應答。

2? TCP函數

2.1? listen()

? ? ? ? #include <sys/socket.h>

? ? ? ? int? listen( int socket,? ?int backlog );

? ? ? ? ? ? ? ? 功能:啟動偵聽,在指定套接字上啟動對連接請求的偵聽功能

? ? ? ? ? ? ? ? sockfd:套接字描述符,在調用此函數之前是一個主動套接字,是不能感知連接請求的

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?在調用此函數并成功返回后,是一個被動套接字,具有感知連接請求的能力。

? ? ? ? ? ? ? ? backlog:未決連接請求隊列的最大長度,一般取不小于1024的值

? ? ? ? ? ? ? ? 返回值:成0-1?

2.2? accept()

????????三次握手始于connect(),終于accept()結束

????????#include <sys/socket.h>

? ? ? ? int accept( int sockfd,? ?struct sockaddr* addr,? ?socklen_t* addrlen );

? ? ? ? ? ? ? ? 功能:等待并接受連接請求,在指定套接字上阻塞,直到連接建立完成

? ? ? ? ? ? ? ? sockfd:偵聽套接字描述符

? ? ? ? ? ? ? ? addr:輸出連接請求發起方的地址信息

? ? ? ? ? ? ? ? addrlen:輸出連接請求發起方的地址信息字節數

? ? ? ? ? ? ? ? 返回值:成功返回可用于后續通信的連接套接字描述符,失敗返回-1?

2.3? recv()

? ? ? ? #include <sys/socket.h>

? ? ? ? ssize_t recv( int sockfd,? ?void* buf,? ?size_t count,? ?int flags );

? ? ? ? ? ? ? ? 功能:接收數據

? ? ? ? ? ? ? ? flags:取0則與read()函數等價。另外也可取以下值

? ? ? ? ? ? ? ? ? ? ? ? ? ?MSG_DONTWAIT? 以非阻塞方式接收數據

? ? ? ? ? ? ? ? ? ? ? ? ? ?MSG_OOB? ? ? ? ? ? ?接收帶外數據

? ? ? ? ? ? ? ? ? ? ? ? ? ?MSG_WAITALL? ? ? 等待所有數據,即不接收到count個字節就不返回

? ? ? ? ? ? ? ? 返回值:成功返回實際接收到的字節數,失敗返回-1??

2.4? send()

? ? ? ? #include <sys/socket.h>

? ? ? ? ssize_t send( int sockfd,? ?void const* buf,? ?size_t count,? ?int flags );

? ? ? ? ? ? ? ? 功能:發送數據

? ? ? ? ? ? ? ? flags:取0則與write()函數等價。另外也可取以下值

? ? ? ? ? ? ? ? ? ? ? ? ? ?MSG_DONTWAIT? 以非阻塞方方式發送數據

? ? ? ? ? ? ? ? ? ? ? ? ? ?MSG_OOB? ? ? ? ? ? ?接收帶外數據

? ? ? ? ? ? ? ? ? ? ? ? ? ?MSG_DONTROUTE?不查路由表,直接在本地網絡中尋找目的主機

? ? ? ? ? ? ? ? 返回值:成功返回實際發送的字節數,失敗返回-1?

3? TCP編程模型

????????

4? 通信終止

4.1? 客戶機主動終止

? ? ? ? 在某個時刻,客戶機認為已經不再需要服務器繼續為其提供服務器了,于是它在接收完最后一個響應包以后,通過close()函數關閉與服務器通信的套接字。

? ? ? ? 客戶機的TCP協議棧向服務器發送FIN分節并得到對方的ACK應答。

? ? ? ? 服務器專門負責與客戶機通信的子進程,此刻正視圖通過recv()接收下一個請求包,結果卻因為收到來自客戶機的FIN分節而返回0。

????????于是該子進程退出收發循環,同時通過close()關閉連接套接字,導致服務器的TCP協議棧向客戶機發送FIN分節,使對方進入TIME_WAIT狀態,并在收到對方ACK應答以后,自己進入CLOSED狀態。

? ? ? ? 隨著收發循環的退出,服務器子進程終止,并在服務器主進程的SIGCHLD(17)信號處理函數中被回收。

????????通信過程宣告結束。

4.2? 服務器主動終止

? ? ? ? 服務器專門負責和某個特定客戶機通信的子進程,在運行過程中出現錯誤,不得不調用close()函數關閉連接套接字,或者直接退出,甚至被信號殺死。于是服務器的TCP協議棧向客戶機發送FIN分節并得到對方的ACK應答。

? ? ? ? A、如果客戶機這時正視圖通過recv()接收響應包,那么該函數會返回0。客戶機可據此判斷服務器已宕機,直接通過close()關閉與服務器通信的套接字,終止通信進程。

? ? ? ? B、如果客戶機這時正視圖通過send()發送請求包,那么該函數并不會失敗,但會導致對方以RST分節做出響應,該響應分節甚至會先于FIN分節被緊隨其后的recv()收到并返回-1,同時置errno為ECONNRESET。這也是終止通信的條件之一。

4.3? 服務器主機不可達(主機崩潰、網絡中斷、路由失效...)

? ? ? ? 在服務器主機不可達的情況下,無論是客戶機還是服務器,它們的TCP協議棧都不可能再有任何數據分節的交換。因此,客戶機通過send()函數發送完請求包以后,會阻塞在recv()上等待來自服務器的響應包。

? ? ? ? 這是客戶機的TCP協議棧會持續地重傳數據分節,視圖得到對方的ACK應答。源自伯克利的實現最多重傳12次,最長等待9分鐘。

? ? ? ? 當TCP最終決定放棄時,會通過recv()向用戶進程返回失敗,并置errno為ETIMEOUT或EHOSTUNREACH或ENETUNREACH。

? ? ? ? 此后,即使服務器主機被重啟,或者通信線路被恢復,由于TCP協議棧已丟失了與先前連接有關的信息,通信依然無法繼續,對所接收到的一切數據一律響應RST分節,只有在重新建立TCP連接后,才能繼續通信。

5? 域名解析

? ? ? ? IP地址是網絡上標識站點的數字地址,為了方便記憶,采用域名來代替IP地址標識站點地址。

? ? ? ? 域名解析就是域名IP地址的轉換過程,由DNS服務器完成。

? ? ? ? 當應用過程需要將一個主機域名映射為IP地址時,就調用域名解析函數,解析函數將待轉換的域名放在DNS請求中,以UDP報文方式發給本地域名服務器。本地的域名服務器查到域名后,將對應的IP地址放在應答報文中返回。

5.1? gethostbyname()

? ? ? ? #include <netdb.h>

? ? ? ? struct hostnet* gethostbyname( char const* host_name );

? ? ? ? ? ? ? ? 功能:通過參數所傳的主機域名,獲取主機信息

? ? ? ? ? ? ? ? host_name:主機域名

? ? ? ? ? ? ? ? 返回值:成功返回表示主機信息的結構體指針,失敗返回NULL?

? ? ? ? 注意,該函數需要在聯網情況下使用。

????????

? ? ? ? struct hostent {

? ? ? ? ? ? ? ? char? ?*h_name;? ? ? ? // 主機官方名

? ? ? ? ? ? ? ? char? ?**h_aliases;? ? // 主機別名表

? ? ? ? ? ? ? ? int? ?h_addrtype;? ? ? ?// 地址類型

? ? ? ? ? ? ? ? int? ?h_length;? ? ? ? ? ?// 地址長度

? ? ? ? ? ? ? ? int? ?**h_addr_list;? ? // IP地址表

? ? ? ? };

? ? ? ? 對于WEB服務器而言,主機官方名有一個,而主機別名可能有多個,這些別名都是為了便于用戶記憶。同時IP地址也可能有多個。

? ? ? ? h_aliases? ?->? ?*? ?->? ?"xxx\n"

? ? ? ? ? ? ? ? ? ? ? ? ? ->? ?*? ?->? ?"xxx\n"

? ? ? ? ? ? ? ? ? ? ? ? ? NULL;

? ? ? ? h_addr_list ->? ?*? ?->? ?in_addr

? ? ? ? ? ? ? ? ? ? ? ? ? ->? ?*? ?->? ?in_addr

? ? ? ? ? ? ? ? ? ? ? ? ? NULL

//tcpser.c  基于tcp的服務器
#include<stdio.h>
#include<string.h>
#include<ctype.h> // toupper()
#include<sys/socket.h>//網絡
#include<sys/types.h>//網絡
#include<arpa/inet.h>//網絡
#include<signal.h>
#include<sys/wait.h>
#include<errno.h>
#include<unistd.h>
//信號處理函數,收尸int main(void){//捕獲17號信號printf("服務器:創建套接字\n");int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){perror("socket");}//組織地址結構printf("服務器:組織地址結構\n");struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(8980); //8980由小端轉大端//ser.sin_addr.s_addr = inet_addr("192.168.222.136");ser.sin_addr.s_addr = INADDR_ANY;//綁定地址結構和套接字printf("服務器:綁定套接字和地址結構\n");if(bind(sockfd,(struct sockaddr*)&ser,sizeof(ser)) == -1){perror("bind");return -1;}//開啟偵聽 套接字 主動-->被動-->感知連接請求printf("服務器:啟動偵聽\n");if(listen(sockfd,1024) == -1){perror("listen");return -1;}for(;;){//等待并建立通信連接printf("服務器:等待并建立通信連接\n");struct sockaddr_in cli;//用來輸出客戶端的地址結構socklen_t len = sizeof(cli);//用來輸出地址結構大小int conn = accept(sockfd,(struct sockaddr*)&cli,&len);if(conn == -1){perror("accept");return -1;}printf("服務器:接收到%s:%hu的客戶端的連接\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));//創建子進程 fork//子進程服務業務處理//業務處理printf("服務器:業務處理\n");for(;;){//接受客戶端發來的小寫的串char buf[64] = {};ssize_t size = read(conn,buf,sizeof(buf)-1);if(size == -1){perror("read");return -1;}if(size == 0){printf("服務器:客戶端斷開連接\n");break;}//轉成大寫for(int i = 0;i < strlen(buf);i++){buf[i] = toupper(buf[i]);}//將轉成大寫的串回傳客戶端if(write(conn,buf,strlen(buf)) == -1){perror("write");return -1;}}printf("服務器:關閉套接字\n");close(conn);}close(sockfd);  return 0;
}#include<stdio.h>
#include<string.h>
#include<ctype.h> // toupper()
#include<sys/socket.h>//網絡
#include<sys/types.h>//網絡
#include<arpa/inet.h>//網絡
#include<signal.h>
#include<sys/wait.h>
#include<errno.h>
#include<unistd.h>
//信號處理函數,收尸
void sigchild(int signum){printf("服務器:捕獲到%d號信號\n",signum);for(;;){pid_t pid = waitpid(-1,NULL,WNOHANG);if(pid == -1){if(errno == ECHILD){printf("服務器:沒有子進程\n");break;}else{perror("waitpid");return ;}}else if(pid == 0){printf("服務器:子進程在運行\n");break;}else{printf("服務器:回收了%d進程的僵尸\n",pid);}}
}int main(void){//捕獲17號信號if(signal(SIGCHLD,sigchild) == SIG_ERR){perror("signal");return -1;}printf("服務器:創建套接字\n");int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){perror("socket");}//組織地址結構printf("服務器:組織地址結構\n");struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(8980);//ser.sin_addr.s_addr = inet_addr("192.168.222.136");ser.sin_addr.s_addr = INADDR_ANY;//接受任意IP地址的數據(服務器可能有多個地址)//綁定地址結構和套接字printf("服務器:綁定套接字和地址結構\n");if(bind(sockfd,(struct sockaddr*)&ser,sizeof(ser)) == -1){perror("bind");return -1;}//開啟偵聽 套接字 主動-->被動-->感知連接請求printf("服務器:啟動偵聽\n");if(listen(sockfd,1024) == -1){perror("listen");return -1;}for(;;){//等待并建立通信連接printf("服務器:等待并建立通信連接\n");struct sockaddr_in cli;//用來輸出客戶端的地址結構socklen_t len = sizeof(cli);//用來輸出地址結構大小int conn = accept(sockfd,(struct sockaddr*)&cli,&len);if(conn == -1){perror("accept");return -1;}printf("服務器:接收到%s:%hu的客戶端的連接\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));//創建子進程 forkpid_t pid = fork();if(pid == -1){perror("fork");return -1;}//子進程服務業務處理//業務處理if(pid == 0){close(sockfd);printf("服務器:業務處理\n");for(;;){//接受客戶端發來的小寫的串char buf[64] = {};ssize_t size = read(conn,buf,sizeof(buf)-1);if(size == -1){perror("read");return -1;}if(size == 0){printf("服務器:客戶端斷開連接\n");break;}//轉成大寫for(int i = 0;i < strlen(buf);i++){buf[i] = toupper(buf[i]);}//將轉成大寫的串回傳客戶端if(write(conn,buf,strlen(buf)) == -1){perror("write");return -1;}}printf("服務器:關閉套接字\n");close(conn);return 0;//!!!!!!}//父進程代碼,關閉通信套接字close(conn);//通信套接字(1個通信套接字對應1個客戶端)}close(sockfd);//偵聽套接字(整個服務器只有1個)return 0;
}//結合tcpcli,1臺虛擬機做服務器執行本代碼,另一臺做客戶端執行tcpcli
//tcpcli.c  基于的客戶端
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>int main(void){//創建套接字printf("客戶端:創建套接字\n");int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){perror("socket");return -1;}//準備服務器的地址結構printf("客戶端:準備服務器的地址結構\n");struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(8980);ser.sin_addr.s_addr = inet_addr("192.168.222.136");//發起連接printf("客戶端:發起連接\n");if(connect(sockfd,(struct sockaddr*)&ser,sizeof(ser)) == -1){perror("connect");return -1;}//業務處理for(;;){//通過鍵盤獲取小寫的串char buf[64] = {};fgets(buf,sizeof(buf),stdin);// ! 退出if(strcmp(buf,"!\n") == 0){break;            }//將小寫的串發送給服務器if(send(sockfd,buf,strlen(buf),0) == -1){perror("send");return -1;}//接受服務器回傳大寫的串if(recv(sockfd,buf,sizeof(buf)-1,0) == -1){perror("recv");return -1;}//顯示printf("%s",buf);}printf("客戶端:關閉套接字\n");close(sockfd);return 0;
}

1

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

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

相關文章

短信驗證碼無法獲取,通過獲取cookies直接登錄

web端&#xff0c;selenium短信驗證碼無法獲取&#xff0c;通過獲取cookies直接登錄 1&#xff0c;先獲取cookies driver webdriver.Chrome() driver.get("") driver.implicitly_wait(2) # 獲取彈窗&#xff0c;并取消 driver.find_element(By.XPATH,"/html/…

智能優化算法應用:基于粒子群算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼

智能優化算法應用&#xff1a;基于粒子群算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼 文章目錄 智能優化算法應用&#xff1a;基于粒子群算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼1.無線傳感網絡節點模型2.覆蓋數學模型及分析3.粒子群算法4.實驗參數設定5.算法結果6.參考文…

Python---異常的綜合案例

☆ 異常的傳遞 需求&#xff1a; ① 嘗試只讀方式打開python.txt文件&#xff0c;如果文件存在則讀取文件內容&#xff0c;文件不存在則提示用戶即可。 ② 讀取內容要求&#xff1a;嘗試循環讀取內容&#xff0c;讀取過程中如果檢測到用戶意外終止程序&#xff0c;則except捕…

個人博客網站如何實現https重定向(301)到http

對于個人網站站注冊比較少的&#xff0c;服務器配置不是很好的&#xff0c;沒必要https,https跳轉到http是要時間的&#xff0c;會影響網站打開的速度。免費的https每年都要更換。個人博客網站https有一段時間了&#xff0c;而且很多頁面都有收錄排名&#xff0c;現在已去掉htt…

基于JavaWeb+SSM+Vue實習記錄微信小程序系統的設計和實現

基于JavaWebSSMVue實習記錄微信小程序系統的設計和實現 源碼獲取入口Lun文目錄前言主要技術系統設計功能截圖訂閱經典源碼專欄Java項目精品實戰案例《500套》 源碼獲取 源碼獲取入口 Lun文目錄 目 錄 摘 要 III Abstract 1 1 系統概述 1 1.1 概述 2 1.2課題意義 3 1.3 主要內…

【Linux系統編程】進度條的編寫

目錄 一&#xff0c;進度條的必備知識 1&#xff0c;緩沖區的粗略介紹 2&#xff0c;回車與換行 二&#xff0c;進度條的初步制作 1&#xff0c;進度條的初步礦建 2&#xff0c;進度條的版本一 3&#xff0c;進度條的版本二 一&#xff0c;進度條的必備知識 1&#xff…

詳細了解STM32----GPIO

提示&#xff1a;永遠支持免費開源知識文檔&#xff0c;喜歡的點個關注吧&#xff01;謝謝&#xff01; 文章目錄 一、什么是GPIO&#xff1f;二、GPIO基本結構三、GPIO的輸入輸出模式1、推挽輸出2、開漏輸出3、復用推挽4、復用開漏1、浮空輸入2、上拉輸入&#xff13;、下拉輸…

FastAPI之嵌套模型

請求體 - 嵌套模型 使用 FastAPI&#xff0c;你可以很隨意的實現模型的嵌套、定義、校驗、記錄文檔&#xff0c;并使用任意深度嵌套的模型&#xff0c;這其實都是FastAPI的核心模塊P一單提成進行做的。。 List 字段 from fastapi import FastAPI from pydantic import BaseM…

基于JavaWeb+SSM+Vue童裝商城小程序系統的設計和實現

基于JavaWebSSMVue童裝商城小程序系統的設計和實現 源碼獲取入口Lun文目錄前言主要技術系統設計功能截圖訂閱經典源碼專欄Java項目精品實戰案例《500套》 源碼獲取 源碼獲取入口 Lun文目錄 目 錄 摘 要 III Abstract 1 1 系統概述 2 1.1 概述 3 1.2課題意義 4 1.3 主要內容 5…

BearPi Std 板從入門到放棄 - 先天篇(1)(階段 : 智慧城市 - 智慧路燈)

簡介 對前面幾篇整合, 做個小小匯總試驗, 使用BearPi E53_SC1擴展板主芯片: STM32L431RCT6串口: Usart1擴展板與主板連接: I2C : I2C1 (光照強度傳感器&#xff1a;BH1750)LED: PB9步驟 創建項目 參考 BearPi Std 板從入門到放棄 - 引氣入體篇&#xff08;1&#xff09;(由零創…

【測試人生】數據同步和遷移的變更注意事項

數據同步或者遷移操作也算是線上數據變更的一種類型。由于涉及的數據量非常大&#xff0c;一旦發生故障&#xff0c;會直接影響線上業務&#xff0c;并且較難止損。從變更風險管控的角度考慮&#xff0c;數據同步或遷移操作也需要走合理的發布窗口&#xff0c;并且在操作前也需…

淺談Google Play ASO 優化

什么是ASO ASO即APP Store Optimization&#xff0c;是用于提高APP在應用市場排名的工具&#xff0c;其實也就是移動產品的SEO工作。 ASO是為了提高該產品的搜索結果成績&#xff0c;提升APP的下載量&#xff0c;針對Google Play來說&#xff0c;ASO就是優化APP頁面。 為什么…

Linux升級nginx版本

處于漏洞修復目的服務器所用nginx是1.16.0版本掃出來存在安全隱患&#xff0c;需要我們升級到1.17.7以上。 一般nginx默認在 /usr/local/ 目錄&#xff0c;這里我的nginx是自定義的路徑安裝在 /app/weblogic/nginx 。 1.查看生產環境nginx版本 cd /app/weblogic/nginx/sbin/…

Redis基礎入門

第1章&#xff1a;引言 大家好&#xff01;我是小黑&#xff0c;今天咱們來聊聊Redis。Redis&#xff0c;這個名字你可能在不少地方聽過&#xff0c;尤其是在后端開發領域&#xff0c;它可是個大名鼎鼎的角色。&#xff0c;Redis是一個開源的內存中數據結構存儲系統&#xff0…

放棄原生SQL:Python中更優雅的數據庫操作

概要 在Python中&#xff0c;通過原生SQL語句進行數據庫操作是一種傳統的方式&#xff0c;但現代的Python開發中&#xff0c;使用ORM&#xff08;Object-Relational Mapping&#xff09;工具和數據庫連接庫可以更加高效和優雅地進行增刪改查操作。本文將詳細介紹Python中放棄原…

解決IDEA中多個項目不在同一窗口下顯示的問題和添加新的git的URL

以上是添加顯示多個項目 以下是給新添加的項目添加git

LeetCode算法題解(單調棧)|LeetCode84. 柱狀圖中最大的矩形

一、LeetCode84. 柱狀圖中最大的矩形 題目鏈接&#xff1a;84. 柱狀圖中最大的矩形 題目描述&#xff1a; 給定 n 個非負整數&#xff0c;用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰&#xff0c;且寬度為 1 。 求在該柱狀圖中&#xff0c;能夠勾勒出來的矩形的最大…

做外貿很多時候還是要學會隨機應變

馬上又要到年底了&#xff0c;相信已經有一部分小伙伴開啟了催單模式&#xff0c;希望客戶盡量在春節前將訂單落實下來&#xff0c;自然也有很多客戶會在春節前的這一段時間開始陸續拜訪自己觀望了很久的工廠。 其實對于貿易公司來說&#xff0c;對于來看工廠的客戶&#xff0…

ChatGPT,作為一種強大的自然語言處理模型,具備顯著優勢,能夠幫助您在各個領域取得突破

2023年隨著OpenAI開發者大會的召開&#xff0c;最重磅更新當屬GPTs&#xff0c;多模態API&#xff0c;未來自定義專屬的GPT。微軟創始人比爾蓋茨稱ChatGPT的出現有著重大歷史意義&#xff0c;不亞于互聯網和個人電腦的問世。360創始人周鴻祎認為未來各行各業如果不能搭上這班車…

Kotlin 作用域函數:理解 apply, let, 和 with

Kotlin提供了幾個作用域函數來優化和簡化代碼的結構。 本文將對比分析 apply, let, 和 with 三個函數。 一、對比分析&#xff1a; apply&#xff1a;在其接收者的上下文中執行代碼塊&#xff0c;并返回接收者對象。let&#xff1a;在其接收者的上下文中執行代碼塊&#xff…