第十三章 學習筆記
第十三章 TCP/IP 網路程式設計 學習筆記
一、網路程式設計簡介
二、TCP/IP協議
TCP:傳輸控制協議
IP:網路協議。有IPv4(32位地址)和IPv6(64位地址)。
TCP/IP的組織結構分為幾個層級,通常稱為TCP/IP堆疊。如圖所示為TCP/IP的各個層級以及每一層級的代表性元件及其功能。
TCP/IP網路中的資料流路徑
三、IP主機和IP地址
-
主機是支援TCP/IP協議的計算機或裝置。每個主機由一個32位的IP地址來標識。為了方便起見32位的IP地址號通常用點記法表示,例如:134121641,其中各個位元組用點號分開。主機也可以用主機名來表示,如dnsleecwsuedu。實際上,應用程式通常使用主機名而不是IP地址。在這個意義上說,主機名就等同於IP地址,因為給定其中一個,我們可以通過DNS(域名系統)(RFC1341987RFC10351987)伺服器找到另一個,它將IP地址轉換為主機名,反之亦然。
-
IP地址分為兩部分,即NetworkID欄位和HostID欄位。根據劃分,IP地址分為A~F類。例如,一個B類IP地址被劃分為一個16位NetworkID,其中前2位是10,然後是一個16位的HostID欄位。發往IP地址的資料包首先被髮送到具有相同networkID的路由器。路由器將通過HostID將資料包轉發到網路中的特定主機。每個主機都有一個本地主機名 localhost預設IP地址為127001。本地主機的鏈路層是一個回送虛擬裝置,它將每個資料包路由回同一個localhost。這個特性可以讓我們在同一臺計算機上執行TCP/IP應用程式而不需要實際連線到網際網路。
四、IP協議
- IP協議用於在 IP主機之間傳送/接收資料包。IP 主機只向接收主機發送資料包,但它不能保證資料包會被髮送到它們的目的地,也不能保證按順序傳送。
五、IP資料包格式
IP資料包由IP頭、傳送方IP地址和接收方IP地址以及資料組成。每個IP資料包的大小最大為64KB。如圖為IP頭格式:
六、路由器
- 路由器是接收和轉發資料包的特殊IP主機。
七、UDP
UDP(使用者資料報協議)(RFC7681980;Comer1988)在IP上執行,用於傳送/接收資料報。與IP類似,UDP不能保證可靠性,但是快速高效。它可用於可靠性不重要的情況。
例如,使用者可以使用ping命令探測目標主機,如ping主機名或pingIP地址
ping是一個向目標主機發送帶時間戳UDP包的應用程式。接收到一個pinging資料包後,目標主機將帶有時間戳的UDP包回送給傳送者,讓傳送者可以計算和顯示往返時間。如果目標主機不存在或宕機,當TTL減小為0時,路由器將會丟棄pingingUDP資料包。在這種情況下,使用者會發現目標主機沒有任何響應。使用者可以嘗試再次ping,或者斷定目標主機宕機。在這種情況下,最好使用UDP,因為不要求可靠性。
八、TCP
- TCP是一種面向連線的協議,用於傳送/接收資料流。TCP也可在IP上執行,但它保證了可靠的資料傳輸。
九、埠編號
- 埠號是分配給應用程式的唯一無符號短整數。要想使用UDP或TCP,應用程式(程序)必須先選擇或獲取一個埠號。前1024個埠號已被預留。其他埠號可供一般使用。應用程式可以選擇一個可用埠號,也可以讓作業系統核心分配埠號。
十、網路和主機位元組序
- 計算機可以使用大端位元組序,也可以使用小端位元組序。在網際網路上,資料始終按網路序排列,這是大端。在小端機器上,例如基於Intel x86的PC,htons()、htonl()、ntohs()、ntohl()等庫函式,可在主機序和網路序之間轉換資料。例如,PC中的埠號1234按主機位元組序(小端)是無符號短整數。必須先通過htons(1234)把它轉換成網路序,才能使用。相反,從網際網路收到的埠號必須先通過ntohs(port)轉換為主機序。
十一、TCP/IP網路中的資料流
十二、網路程式設計
在伺服器 — 客戶機計算模型中,我們首先在伺服器主機上執行伺服器程序。然後,我們從客戶主機執行客戶及。在UDP中,伺服器等待來自客戶機的戶籍包,處理資料包並生成對客戶及的相應。在TCP中,伺服器等待客戶機連線。客戶機首先連線到伺服器,在客戶機和伺服器之間建立一個虛擬電路。
十三、套接字程式設計
套接字地址
TCP/IP網路的sin_family始終設定位AF_INET
sin_port包含網路位元組順序排列的埠號。
sin_addr是按網路位元組順序排列的主機IP地址
十四、程式設計例項##
程式碼:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#define MAXLINE 256
#define PORT 7777
void sys_err(char *msg){
perror(msg);
exit(-1);
}
int main(int argc , char **argv){
int sockFd,n;
char recvLine[MAXLINE];
struct sockaddr_in servAddr;
if (argc != 2) {
sys_err("usage: a.out <IPaddress>");
}
sockFd=socket(AF_INET,SOCK_STREAM,0);
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(PORT);
if (inet_pton(AF_INET,argv[1],&servAddr.sin_addr) <= 0) {
sys_err("inet_pton error");
}
connect(sockFd,(struct sockaddr *)&servAddr,sizeof(servAddr));
while((n=read(sockFd,recvLine,MAXLINE)) >0 ){
recvLine[n] = '\0';
if(fputs(recvLine,stdout) == EOF){
sys_err("fputs error");
}
}
if(n <0){
sys_err("read error");
}
return 0;
}