第十三章:TCP/IP和網(wǎng)絡(luò)編程

TCP/IP協(xié)議

TCP/IP是互聯(lián)網(wǎng)的基礎(chǔ)。TCP代表傳輸控制協(xié)議。IP代表互聯(lián)網(wǎng)協(xié)議。目前有兩個(gè)版本的IP,即IPv4和IPv6.前者使用32位地址,后者使用128位地址。IPv4仍然是目前使用最多的IP版本。TCP/IP的組織結(jié)構(gòu)分為幾個(gè)層級(jí),通常稱為TCP/IP堆棧。

IP主機(jī)和IP地址

主機(jī)是支持TCP/IP協(xié)議的計(jì)算機(jī)或設(shè)備。每個(gè)主機(jī)由一個(gè)32位的IP地址來標(biāo)識(shí)。為了方便起見32位的IP地址號(hào)通常用點(diǎn)記法表示,例如:134.121.64.1,其中各個(gè)字節(jié)用點(diǎn)號(hào)分開。主機(jī)也可以用主機(jī)名來表示,如dnsl.eec.wsu.edu。實(shí)際上,應(yīng)用程序通常使用主機(jī)名而不是IP地址。在這個(gè)意義上說,主機(jī)名就等同于IP地址,因?yàn)榻o定其中一個(gè),我們可以通過DNS(域名系統(tǒng))(RFC1341987RFC10351987)服務(wù)器找到另一個(gè),它將IP地址轉(zhuǎn)換為主機(jī)名,反之亦然。
IP地址分為兩部分,即NetworkID字段和HostID字段。發(fā)往IP地址的數(shù)據(jù)包首先被發(fā)送到具有相同networkID的路由器。路由器將通過HostID將數(shù)據(jù)包轉(zhuǎn)發(fā)到網(wǎng)絡(luò)中的特定主機(jī)。每個(gè)主機(jī)都有一個(gè)本地主機(jī)名。localhost默認(rèn)IP地址為127001。本地主機(jī)的鏈路層是一個(gè)回送虛擬設(shè)備,它將每個(gè)數(shù)據(jù)包路由回同一個(gè)localhost。這個(gè)特性可以讓我們?cè)谕慌_(tái)計(jì)算機(jī)上運(yùn)行TCP/IP應(yīng)用程序而不需要實(shí)際連接到互聯(lián)網(wǎng)。

IP協(xié)議

  • IP協(xié)議用于在IP主機(jī)之間發(fā)送/接收數(shù)據(jù)包,IP盡最大努力運(yùn)行。IP主機(jī)只向接收主機(jī)發(fā)送數(shù)據(jù)包,這意味著IP并非可靠的協(xié)議。
  • 必要時(shí),必須在IP層上實(shí)現(xiàn)可靠性

IP數(shù)據(jù)包格式

  • IP數(shù)據(jù)包由IP頭、發(fā)送方IP地址和接收方IP地址以及數(shù)據(jù)組成

UDP

  • UDP在IP上運(yùn)行,用于發(fā)送/接收數(shù)據(jù)
  • UDP不能保證可靠性,但是快速高效,可用于可靠性不重要的情況

TCP

  • TCP是一種面向連接的協(xié)議,用于發(fā)送/接收數(shù)據(jù)流
  • TCP可在IP上運(yùn)行,它保證了可靠的數(shù)據(jù)傳輸

端口編號(hào)

  • 每個(gè)應(yīng)用程序由三個(gè)組成部分唯一標(biāo)識(shí)
    應(yīng)用程序=(主機(jī)IP,協(xié)議,端口號(hào))

TCP/IP網(wǎng)絡(luò)中的數(shù)據(jù)流

套接字編程

  • TCP/IP的用戶界面是通過一系列C語言庫函數(shù)和系統(tǒng)調(diào)用來實(shí)現(xiàn)的,這些函數(shù)和系統(tǒng)調(diào)用統(tǒng)稱為套接字API

套接字地址

struct sockaddr_in {
    sa_family_t sin_family; 
    in_port_t sin_port; 
    struct in_addr sin_addr;
};
struct in_addr {
    uint32_t s_addr;
};

套接字API

  • int套接字(int域,int類型,int協(xié)議)
    示例:
int udp_sock = socket(AF_INET, SOCK_DGRAM, 0);:將會(huì)創(chuàng)建一個(gè)用于發(fā)送/接收UDP數(shù)據(jù)報(bào)的套接字。
int tcp_sock = socket(AF_INET, SOCK_STREAM, 0);:將會(huì)創(chuàng)建一個(gè)用于發(fā)送/接收數(shù)據(jù)流的面向連接的TCP套接
字c
  • int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen)
    • bind()系統(tǒng)調(diào)用將addr指定的地址分配給文件描述符sockfd所引用的套接字addrlen 指定addr所指向地址結(jié)構(gòu)的大小(以字節(jié)為單位)。對(duì)于用于聯(lián)系其他UDP服務(wù)器主機(jī)的UDP套接字,必須綁定到客戶機(jī)地址,允許服務(wù)器發(fā)回應(yīng)答。對(duì)于用于接收客戶機(jī)連接的TCP套接字,必須先將其綁定到服務(wù)器主機(jī)地址。
  • UDP套接字
    • UDP套接字使用scndto()/recvfrom()來發(fā)送/接收數(shù)據(jù)報(bào)。
  • TCP套接字
    int Iistcn(int sockfd, int backlog);
    • listen()將sockfd引用的套接字標(biāo)記為將用于接收連入連接的套接字。backlog參數(shù)定義了等 待連接的最大隊(duì)列長(zhǎng)度。
      int accept(int sockfd, struct sockaddr *addr, sockien_t *addrlen);
    • accept()系統(tǒng)調(diào)用與基于連接的套接字一起使用。它提取等待連接隊(duì)列上的第一個(gè)連接請(qǐng)求 用于監(jiān)聽套接字sockfd,創(chuàng)建一個(gè)新的連接套接字,并返回一個(gè)引用該套接字的新文件描 述符,與客戶機(jī)主機(jī)連接。在執(zhí)行accept()系統(tǒng)調(diào)用時(shí),TCP服務(wù)器阻塞,直到客戶機(jī)通過 coimectO建立連接。
      int connect(int sockfd, const struct sockaddr *addr, socklen t addrlen);
    • connect()系統(tǒng)調(diào)用將文件描述符sockfd引用的套接字連接到addr指定的地址,addrlen參數(shù) 指定addr的大小。addr中的地址格式由套接字sockfd的地址空間決定。
  • send()/read()以及recv/write()

實(shí)踐

server


client


蘇格拉底提問