建立乙個 tcp 連線時會發生下述情形:
1. 伺服器必須準備好接受外來的連線。這通常通過呼叫 socket、bind 和 listen 這三個函式來完成,我們稱之為被動開啟。
2. 客戶通過呼叫 connect 發起主動開啟,這導致客戶tcp傳送乙個syn(同步)分節,標識希望連線的伺服器端口以及初始序號。通常syn分節不攜帶資料,其所在ip資料報只含有乙個ip首部、乙個tcp首部及可能有的tcp選項。
3. 伺服器傳送回乙個包含伺服器初始序號以及對客戶端 syn 段確認的 syn + ack 段作為應答,由於乙個 syn 占用乙個序號,因此確認序號設定為客戶端初始序號加 1。
4. 客戶端傳送確認序號為伺服器初始序號加 1 的 ack 段,對伺服器 syn 段進行確認。
這種交換至少需要三個分組,因此稱之為tcp的三路握手。
一旦tcp建立連線,客戶/伺服器之間便可以進行資料通訊。
1. 伺服器端
#include#include#include#include#include#include#includein.h>#include #define port 6666 int main(int argc,char **ar**) bzero(&ser_addr,sizeof(ser_addr)); /*在待**到該tcp套介面(sockfd)的網際套介面位址結構中填入通配位址(inaddr_any) 和伺服器的眾所周知埠(port,這裡為6666),這裡**通配位址是在告知系統:要是系統是 多宿主機(具有多個網路連線的主機),我們將接受宿位址為任何本地介面的位址*/ser_addr.sin_family =af_inet; ser_addr.sin_addr.s_addr =htonl(inaddr_any); ser_addr.sin_port =htons(port); //將網際套介面位址結構**到該套介面 err = bind(ser_sockfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr)); if(err == -1) //將套介面轉換為乙個監聽套介面,監聽等待來自客戶端的連線請求 err = listen(ser_sockfd,5); if(err == -1) printf("listen the port:\n"); while(1) //資料傳輸 while(1) recvline[n] = '\0'; printf("recv data is:%s\n",recvline); printf("input your words:"); scanf("%s",sendline); send(cli_sockfd,sendline,strlen(sendline),0); } close(cli_sockfd); } close(ser_sockfd); return 0; }1.首先通過 socket 函式建立套接字,此時套接字資料結構字段並未填充,在使用之前必須呼叫過程來填充對應字段,這裡在位址結構中填入通配位址(inaddr_any),通配位址就是指定位址為 0.0.0.0 的位址,表示伺服器接受機器上所有ip位址的連線,用於多ip機器上。這樣無論客戶 connect 哪個ip位址,伺服器端都會接收到請求,即接受宿位址為任何本地介面的位址。如果是指定位址,那麼機器只有 connect 這個位址才能成功。後面是填充埠號,如果指定為 0,則由系統隨機選擇乙個未被使用的埠。
2. bind 將沒有指定埠的 socket(ser_sockfd)繫結到我們指定的埠上(通配位址+指定埠號),伺服器是通過它們的眾所周知埠被大家認識的。這樣 socket(ser_sockfd)就與指定的埠產生了關聯,即指向了指定埠。
3. listen 將套介面轉換為乙個監聽套介面,被動開啟,允許監聽客戶端的連線請求,然後 accept 客戶端的連線請求,沒有請求則阻塞。
5. accept 成功後,將建立新的套接字,並為新套接字分配乙個套介面描述符,該套接字除了記錄本地(伺服器)的ip和埠號資訊外,還記錄了目的(客戶)ip和埠號資訊。伺服器與客戶的通訊則是通過該新建立的套接字(已連線套接字)進行。
#include#include#include#include#include#include#includein.h> #define port 6666 int main(int argc,char **ar**) bzero(&addr_ser,sizeof(addr_ser)); /*用通配位址和指定埠號裝填乙個網際介面位址結構*/addr_ser.sin_family =af_inet; addr_ser.sin_addr.s_addr =htonl(inaddr_any); addr_ser.sin_port =htons(port); //tcp:客戶(sockfd)向伺服器(套介面位址結構)發起連線,主動請求 //伺服器的ip位址和埠號有引數addr_ser指定 err = connect(sockfd,(struct sockaddr *)&addr_ser,sizeof(addr_ser)); if(err == -1) printf("connect with server...\n"); //資料傳輸 while(1) return 0; }1. 客戶端同樣通過 socket 建立套接字,tcp 客戶通常不把ip位址**到它的套介面上,當連線套介面時,核心將根據所用外出網路介面來確定源ip位址,並選擇乙個臨時埠作為源埠。
2. 用通配位址和指定埠填充的是待連線伺服器端的套接字位址結購,這裡採用的是通配位址,由於伺服器端指定的是通配位址,即接受機器上所有ip位址的連線,同樣客戶也可向機器上任何ip位址發起連線,伺服器端都會接收到。
3. 客戶端向伺服器發起連線請求,connect 成功後,其請求連線的伺服器的ip和埠號資訊將會寫入該套接字,這樣該套接字也同時記錄了本地和目的的ip位址和埠資訊。也就可以進行通訊了。
結果如下:
簡單TCP客戶 伺服器的理解
1.伺服器部分 socket bind listen之後,for迴圈內accept獲取 已連線套接字 描述符 fork子程式處理該連線的資料傳輸。2.客戶端部分 socket connect之後,呼叫資料傳送函式向該套接字內寫資料,即傳送資料。1.程序exit後,會關閉所有開啟的檔案描述符,包括套接...
tcp 客戶 伺服器程式示例
1 client 從標準輸入讀入一行文字,並寫給伺服器。2 伺服器從網路輸入讀入這行文字,並回射給客戶。3 客戶從網路輸入讀入這行回射的文字,顯示在標準輸出上 標準輸入 fgets tcp 客戶 write read tcp 伺服器 標準輸出 fputs tcp 客戶 read write tcp ...
TCP客戶 伺服器程式例項
1.概述 這章的tcp客戶 伺服器模型 2.tcp回射伺服器程式 1 main函式 include unp.h int main int argc,char argv close connfd parent closes connected socket 2 str echo函式 include u...