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