1) 物理層
定義了網(wǎng)絡的物理結(jié)構(gòu)、傳輸?shù)碾姶艠藴?、Bit流的編碼及網(wǎng)絡的時間原則。
2)數(shù)據(jù)鏈路層
在兩個主機上建立數(shù)據(jù)鏈路連接,向物理層傳輸數(shù)據(jù)信號,并對信號進行處理使之無差錯
并合理地傳輸。
3) 網(wǎng)絡層
主要負責路由、選擇合適的路徑和進行阻塞控制等功能。
4) 傳輸層
向用戶提供可靠的端到端服務,它屏蔽了下層的數(shù)據(jù)通信細節(jié),讓用戶及應用程序不需要
考慮實際的通信方法。
5) 會話層
主要負責兩個會話進程之間的通信,即兩個會話層實體之間的信息交換和管理數(shù)的交換。
6) 表示層
處理通信信號的表示方法,進行不同格式之間的翻譯,并負責數(shù)據(jù)的加密解密,數(shù)據(jù)的
壓縮與恢復。
7) 應用層
保持應用程序之間建立連接所需要的數(shù)據(jù)記錄,為用戶服務。
一、數(shù)據(jù)封裝:
以太網(wǎng)幀:以太網(wǎng)頭部、IP頭部、TCP頭部、HTTP頭部、以太網(wǎng)尾部
IP數(shù)據(jù)報: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ū)動-IP-TCP-應用程序
二、IP地址:
1、使用IP協(xié)議通訊的主機都有IP地址,如:192.168.2.10
2、在計算機中,IPv4地址用一個32位無符號整數(shù)表示
一、端口號
TCP/UDP協(xié)議使用16位整數(shù)存儲端口號,所以每個主機擁有 65,535 個端口
一些端口被IANA分配給指定應用
21: FTP
23: Telnet
80: HTTP
RFC 1700 (大約有2000個保留端口)
二、TCP和UDP的區(qū)別
1、TCP提供一種面向連接的、可靠的字節(jié)流服務
2、UDP是無連接的、不可靠的數(shù)據(jù)協(xié)議報
Socket套接字
1)linux中的網(wǎng)絡編程通過socket接口實現(xiàn)。Socket既是一種特殊的IO,一個完整的Socket都有一個相關(guān)描述
{協(xié)議,本地地址,本地端口,遠程地址,遠程端口};每一個Socket 有一個本地的唯一Socket號,由操作系統(tǒng)分配。
函數(shù)原型
include<sys/socket.h>
int socket(int domain,int type,int protocol)
返回:成功返回描述符,出錯返回-1
參數(shù):
domain
AF_INET IPv4因特網(wǎng)域
AF_INET6 IPv6因特網(wǎng)域
AF_UNIX unix域
AF_UNSPEC 未指定
protocol
通常為0,表示按給定的域和套接字類型選擇默認協(xié)議。
type
SOCK_STREAM 流式的套接字可以提供可靠的、面向連接的通訊流。它使用了TCP協(xié)議。TCP保證了數(shù)據(jù)傳輸?shù)恼_性和順序性。
SOCK_DGRAM 數(shù)據(jù)報套接字定義了一種無連接的服務,數(shù)據(jù)通過相互獨立的報文進行傳輸,是無序的,并且不保證可靠,無差錯。使用數(shù)據(jù)報協(xié)議UDP協(xié)議。
SOCK_RAW 原始套接字允許對低層協(xié)議如IP或ICMP直接訪問,主要用于新的網(wǎng)絡協(xié)議實現(xiàn)的測試等。
SOCK_SEQPACKET 長度固定、有序、可靠的面向鏈接報文傳遞
字節(jié)序轉(zhuǎn)換函數(shù)
uint32_t hton(uint32_t hostlong)
將一個32位整數(shù)由主機字節(jié)序轉(zhuǎn)換成網(wǎng)絡字節(jié)序
uint16_t htons(uint16_t hostshort )
將一個16位整數(shù)由主機字節(jié)序轉(zhuǎn)換成網(wǎng)絡字節(jié)序
uint32_t ntohl(uint32_t netlong)
將一個32位整數(shù)由網(wǎng)絡字節(jié)序轉(zhuǎn)換成主機字節(jié)序
uint16_t ntohs(uint16_t netshort)
將一個16位整數(shù)由網(wǎng)絡字節(jié)序轉(zhuǎn)換成主機字節(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 包含一些遠程電腦的地址、端口和套接字的數(shù)目,它里面的數(shù)據(jù)是雜溶在一起的
在傳遞給需要地址結(jié)構(gòu)的函數(shù)時,把指向該結(jié)構(gòu)的指針轉(zhuǎn)換成(struct sockaddr *)傳遞進去。
因特網(wǎng)地址結(jié)構(gòu)
struct in_addr{
in_addr_t s_addr /* ipv4地址 */
}
struct sockaddr_in{
short int sin_family; /* Internet地址族如AF_INET(主機字節(jié)序) /
unsigned short int sin_port;/ 端口號,16位值(網(wǎng)絡字節(jié)序) /
struct in_addr sin_addr; / Internet地址,32位IPv4地址(網(wǎng)絡字節(jié)序) /
unsigned char sin_zero[8]; / 添0(為了格式對齊的填充位) */
}
IPv4地址族和字符地址間的轉(zhuǎn)換
include<arp/inet.h>
const char *inet_ntop(int domain,const void *restrict addr,char *restrict str,socklen_t size);
返回:成功返回地址字符串指針,出錯返回NULL
功能:網(wǎng)絡字節(jié)序轉(zhuǎn)換成點分十進制
int inet_pton(int domain,const char *restrict str,void *restrict addr);
返回:成功返回1,無效格式返回0,出錯返回-1
功能:點分十進制轉(zhuǎn)換為網(wǎng)絡字節(jié)序
參數(shù)
domain: Internet地址族,如AF_INET
addr: Internet地址,32位IPv4地址(網(wǎng)絡字節(jié)序)
str: 地址字符串(點分十進制)指針
size: 地址字符串大小
填寫IPv4地址族結(jié)構(gòu)案例
struct sockaddr_in sin; //定義一個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);//填寫端口號(網(wǎng)絡字節(jié)序)
//填充sin_addr
if(inet_pton(AF_INET,"192.168.2.1",&sin.sin_addr.s_addr)<=0){
//錯誤處理
}
printf("%s\n",inet_ntop(AF_INET,&sin.sin_addr.s_addr,buf,sizeof(buf)));
TCP客戶端服務器編程模型
服務器端調(diào)用序列
調(diào)用socket函數(shù)創(chuàng)建套接字
調(diào)用bind綁定本地地址和端口
調(diào)用listen啟動監(jiān)聽
調(diào)用accept從已連接列隊中提取客服連接
調(diào)用I/O函數(shù)(read/write)與客戶端通訊
調(diào)用close關(guān)閉套接字
客戶端調(diào)用序列
調(diào)用socket函數(shù)創(chuàng)建套接字
調(diào)用connect連接服務器端
調(diào)用I/O函數(shù)(read/write)與客戶端通訊
調(diào)用close關(guān)閉套接字
服務器
socket()
bind()
listen()
客服端
accept() socket()
阻塞,等待客戶數(shù) <- 建立連接 ---- connect()
read() <------- 請求數(shù)據(jù) ----- write()
處理服務請求
write() ------- 應答數(shù)據(jù) -----> read()
close() close()
套接字與地址綁定
綁定地址
#include <sys/socket.h>
int bind(int sockfd,const struct sockaddr *addr,socklen_t len);
返回:成功返回0,出錯返回-1
查找綁定到套接字的地址
int getsockname(int sockfd,struct sockaddr *restrict addr,socklen_t *restrict alenp);
返回:成功返回0,出錯返回-1
獲取對方地址
int getpeername(int sockfd,struct sockaddr *restrict addr,socklen_t *restrict alenp);
返回:成功返回0,出錯返回-1
建立連接
服務器端
#include <sys/socket.h>
int listen(int sockfd,int backlog);
返回:成功返回0,出錯返回-1。backlog指定進行客服端連接排隊的隊列長度
int accept(int sockfd,struct sockaddr *restrict addr,socklen_t *restrict len);
客戶端
int connect(int sockfd,const struct sockaddr *addr,socklen_t len);
返回:成功返回0,出錯返回-1