1) 物理層
定義了網(wǎng)絡(luò)的物理結(jié)構(gòu)、傳輸?shù)碾姶艠?biāo)準(zhǔn)禀酱、Bit流的編碼及網(wǎng)絡(luò)的時(shí)間原則臀防。
2)數(shù)據(jù)鏈路層
在兩個(gè)主機(jī)上建立數(shù)據(jù)鏈路連接,向物理層傳輸數(shù)據(jù)信號(hào)毁枯,并對(duì)信號(hào)進(jìn)行處理使之無差錯(cuò)
并合理地傳輸慈缔。
3) 網(wǎng)絡(luò)層
主要負(fù)責(zé)路由、選擇合適的路徑和進(jìn)行阻塞控制等功能种玛。
4) 傳輸層
向用戶提供可靠的端到端服務(wù)藐鹤,它屏蔽了下層的數(shù)據(jù)通信細(xì)節(jié),讓用戶及應(yīng)用程序不需要
考慮實(shí)際的通信方法赂韵。
5) 會(huì)話層
主要負(fù)責(zé)兩個(gè)會(huì)話進(jìn)程之間的通信娱节,即兩個(gè)會(huì)話層實(shí)體之間的信息交換和管理數(shù)的交換。
6) 表示層
處理通信信號(hào)的表示方法祭示,進(jìn)行不同格式之間的翻譯肄满,并負(fù)責(zé)數(shù)據(jù)的加密解密,數(shù)據(jù)的
壓縮與恢復(fù)质涛。
7) 應(yīng)用層
保持應(yīng)用程序之間建立連接所需要的數(shù)據(jù)記錄悄窃,為用戶服務(wù)。
一蹂窖、數(shù)據(jù)封裝:
以太網(wǎng)幀:以太網(wǎng)頭部轧抗、IP頭部、TCP頭部瞬测、HTTP頭部横媚、以太網(wǎng)尾部
IP數(shù)據(jù)報(bào):IP頭部纠炮、TCP頭部、HTTP頭部灯蝴、數(shù)據(jù)
TCP段:TCP頭部恢口、HTTP頭部、數(shù)據(jù)
HTTP頭部穷躁、數(shù)據(jù)
數(shù)據(jù)
IP頭部——數(shù)據(jù)總共46-1500字節(jié)
以太網(wǎng):以太網(wǎng)驅(qū)動(dòng)-IP-TCP-應(yīng)用程序
二耕肩、IP地址:
1、使用IP協(xié)議通訊的主機(jī)都有IP地址问潭,如:192.168.2.10
2猿诸、在計(jì)算機(jī)中,IPv4地址用一個(gè)32位無符號(hào)整數(shù)表示
一狡忙、端口號(hào)
TCP/UDP協(xié)議使用16位整數(shù)存儲(chǔ)端口號(hào)梳虽,所以每個(gè)主機(jī)擁有 65,535 個(gè)端口
一些端口被IANA分配給指定應(yīng)用
21: FTP
23: Telnet
80: HTTP
RFC 1700 (大約有2000個(gè)保留端口)
二、TCP和UDP的區(qū)別
1灾茁、TCP提供一種面向連接的窜觉、可靠的字節(jié)流服務(wù)
2、UDP是無連接的北专、不可靠的數(shù)據(jù)協(xié)議報(bào)
Socket套接字
1)linux中的網(wǎng)絡(luò)編程通過socket接口實(shí)現(xiàn)禀挫。Socket既是一種特殊的IO,一個(gè)完整的Socket都有一個(gè)相關(guān)描述
{協(xié)議拓颓,本地地址语婴,本地端口,遠(yuǎn)程地址录粱,遠(yuǎn)程端口};每一個(gè)Socket 有一個(gè)本地的唯一Socket號(hào)画拾,由操作系統(tǒng)分配啥繁。
函數(shù)原型
include<sys/socket.h>
int socket(int domain,int type,int protocol)
返回:成功返回描述符,出錯(cuò)返回-1
參數(shù):
domain
AF_INET IPv4因特網(wǎng)域
AF_INET6 IPv6因特網(wǎng)域
AF_UNIX unix域
AF_UNSPEC 未指定
protocol
通常為0青抛,表示按給定的域和套接字類型選擇默認(rèn)協(xié)議旗闽。
type
SOCK_STREAM 流式的套接字可以提供可靠的、面向連接的通訊流蜜另。它使用了TCP協(xié)議适室。TCP保證了數(shù)據(jù)傳輸?shù)恼_性和順序性。
SOCK_DGRAM 數(shù)據(jù)報(bào)套接字定義了一種無連接的服務(wù)举瑰,數(shù)據(jù)通過相互獨(dú)立的報(bào)文進(jìn)行傳輸捣辆,是無序的,并且不保證可靠此迅,無差錯(cuò)汽畴。使用數(shù)據(jù)報(bào)協(xié)議UDP協(xié)議旧巾。
SOCK_RAW 原始套接字允許對(duì)低層協(xié)議如IP或ICMP直接訪問,主要用于新的網(wǎng)絡(luò)協(xié)議實(shí)現(xiàn)的測試等忍些。
SOCK_SEQPACKET 長度固定鲁猩、有序、可靠的面向鏈接報(bào)文傳遞
字節(jié)序轉(zhuǎn)換函數(shù)
uint32_t hton(uint32_t hostlong)
將一個(gè)32位整數(shù)由主機(jī)字節(jié)序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序
uint16_t htons(uint16_t hostshort )
將一個(gè)16位整數(shù)由主機(jī)字節(jié)序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序
uint32_t ntohl(uint32_t netlong)
將一個(gè)32位整數(shù)由網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成主機(jī)字節(jié)序
uint16_t ntohs(uint16_t netshort)
將一個(gè)16位整數(shù)由網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成主機(jī)字節(jié)序
通用地址結(jié)構(gòu)
include<sys/socket.h>
struct sockaddr{
unsigned short sa_family; /* Internet地址族罢坝,AF_xxxx /
char sa_data[14]; / 14 bytes 的協(xié)議地址 */
}
sa_family 一般來說廓握,IPV4使用AF_INET。
sa_data 包含一些遠(yuǎn)程電腦的地址嘁酿、端口和套接字的數(shù)目隙券,它里面的數(shù)據(jù)是雜溶在一起的
在傳遞給需要地址結(jié)構(gòu)的函數(shù)時(shí),把指向該結(jié)構(gòu)的指針轉(zhuǎn)換成(struct sockaddr *)傳遞進(jìn)去痹仙。
因特網(wǎng)地址結(jié)構(gòu)
struct in_addr{
in_addr_t s_addr /* ipv4地址 */
}
struct sockaddr_in{
short int sin_family; /* Internet地址族如AF_INET(主機(jī)字節(jié)序) /
unsigned short int sin_port;/ 端口號(hào)是尔,16位值(網(wǎng)絡(luò)字節(jié)序) /
struct in_addr sin_addr; / Internet地址,32位IPv4地址(網(wǎng)絡(luò)字節(jié)序) /
unsigned char sin_zero[8]; / 添0(為了格式對(duì)齊的填充位) */
}
IPv4地址族和字符地址間的轉(zhuǎn)換
include<arp/inet.h>
const char *inet_ntop(int domain,const void *restrict addr,char *restrict str,socklen_t size);
返回:成功返回地址字符串指針开仰,出錯(cuò)返回NULL
功能:網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成點(diǎn)分十進(jìn)制
int inet_pton(int domain,const char *restrict str,void *restrict addr);
返回:成功返回1拟枚,無效格式返回0,出錯(cuò)返回-1
功能:點(diǎn)分十進(jìn)制轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序
參數(shù)
domain: Internet地址族众弓,如AF_INET
addr: Internet地址恩溅,32位IPv4地址(網(wǎng)絡(luò)字節(jié)序)
str: 地址字符串(點(diǎn)分十進(jìn)制)指針
size: 地址字符串大小
填寫IPv4地址族結(jié)構(gòu)案例
struct sockaddr_in sin; //定義一個(gè)sockaddr_in結(jié)構(gòu)體
char buf[16];
memset(&sin,0,sizeof(sin)); //內(nèi)存清零
sin.sin_family = AF_INET; //填寫Internet地址族
sin.sin_port = htons((short)3001);//填寫端口號(hào)(網(wǎng)絡(luò)字節(jié)序)
//填充sin_addr
if(inet_pton(AF_INET,"192.168.2.1",&sin.sin_addr.s_addr)<=0){
//錯(cuò)誤處理
}
printf("%s\n",inet_ntop(AF_INET,&sin.sin_addr.s_addr,buf,sizeof(buf)));
TCP客戶端服務(wù)器編程模型
服務(wù)器端調(diào)用序列
調(diào)用socket函數(shù)創(chuàng)建套接字
調(diào)用bind綁定本地地址和端口
調(diào)用listen啟動(dòng)監(jiān)聽
調(diào)用accept從已連接列隊(duì)中提取客服連接
調(diào)用I/O函數(shù)(read/write)與客戶端通訊
調(diào)用close關(guān)閉套接字
客戶端調(diào)用序列
調(diào)用socket函數(shù)創(chuàng)建套接字
調(diào)用connect連接服務(wù)器端
調(diào)用I/O函數(shù)(read/write)與客戶端通訊
調(diào)用close關(guān)閉套接字
服務(wù)器
socket()
bind()
listen()
客服端
accept() socket()
阻塞,等待客戶數(shù) <- 建立連接 ---- connect()
read() <------- 請(qǐng)求數(shù)據(jù) ----- write()
處理服務(wù)請(qǐng)求
write() ------- 應(yīng)答數(shù)據(jù) -----> read()
close() close()
套接字與地址綁定
綁定地址
#include <sys/socket.h>
int bind(int sockfd,const struct sockaddr *addr,socklen_t len);
返回:成功返回0谓娃,出錯(cuò)返回-1
查找綁定到套接字的地址
int getsockname(int sockfd,struct sockaddr *restrict addr,socklen_t *restrict alenp);
返回:成功返回0脚乡,出錯(cuò)返回-1
獲取對(duì)方地址
int getpeername(int sockfd,struct sockaddr *restrict addr,socklen_t *restrict alenp);
返回:成功返回0,出錯(cuò)返回-1
建立連接
服務(wù)器端
#include <sys/socket.h>
int listen(int sockfd,int backlog);
返回:成功返回0滨达,出錯(cuò)返回-1奶稠。backlog指定進(jìn)行客服端連接排隊(duì)的隊(duì)列長度
int accept(int sockfd,struct sockaddr *restrict addr,socklen_t *restrict len);
客戶端
int connect(int sockfd,const struct sockaddr *addr,socklen_t len);
返回:成功返回0,出錯(cuò)返回-1