OSI七層模型:
OSI 模型? --> 開放系統互聯模型? --> 分為7層:
? ? ? ?理想模型? --> 尚未實現
? ? ? ? 1.應用層 ?QQ
?? ??? ? ? ? ? ? ? ? ? 應用程序的接口
?? ??? ?2.表示層 ?加密解密 ?gzip
?? ??? ? ? ? ? ? ? ? ? 將接收的數據進行解釋(機器->人)
?? ??? ?3.會話層 ?網絡斷開,連接狀態,keep-close keep-alive
?? ??? ? ? ? ? ? ? ? ? 通信雙方管理會話
?? ??? ?4.傳輸層:tcp ?udp ?協議 ?文件 ? ?視頻,音頻
? ? ? ? ? ? ? ? ? ? ? ? (傳數據)
?? ??? ?5.網絡層ip ? NAT
?? ??? ??? ?實現數據從源經過多條鏈路到目的地的轉發(找主機)
?? ??? ?6.鏈路層 ?交換機 ?數據的格式化 ?幀 校驗
?? ??? ? ? ? ? ? ? ?將電信號封裝,建立數據鏈路,實現點對點數據傳輸
?? ??? ?7.物理層:100Mb/8 ?Gbits ? 100MB 同軸電纜 10Gb ? ?2.4G 5G
?? ??? ? ? ? ? ? ? ? 可通過物理介質傳播的電信號
TCP/IP模型:
? TCP/IP模型? --> 網際互聯模型? ?--> 分為4層:
? ?? ?實用模型? --> 工業標準
????????1.應用層 ?---> ?應用程序(用戶與應用程序的接口)(會話層+表示層+應用層)
?? ??? ?2.傳輸層 ?---> ?端口號tcp udp? (傳數據)
?? ??? ?3.網絡層 ?---> ?IP 地址(找主機)
?? ??? ?4.接口層 ?---> ?網卡 驅動 ?1GB(連結互聯網的基礎設施)(物理層+鏈路層)
網絡基礎
IP地址 = 網絡位 + 主機位
010 3333344444
IP地址的分類: 點分十進制 ? ipv4(4字節(32位)數據,42億個地址,已耗盡)?
?? ??? ? ? ? ? ? ipv6(16字節(128位)數據,地址很多,未耗盡
A類:?? ?超大規模性網絡
?? ??? ??? ??? ??? ?8?? ?8?? ?8?? ?8
?? ??? ?1.0.0.0 - 126.255.255.255 ?126.1.1.1?
?? ??? ??? ??? ??? ??? ??? ??? ??? ?126.1.1.2
?? ??? ?255.0.0.0 ? ?
?? ??? ?私有:
?? ??? ?10.0.0.0 - 10.255.255.255
?? ??? ?127.0.0.1
?? ?B類:?? ?大中規模型網絡
?? ??? ?128.0.0.0 - 191.255.255.255
?? ??? ?128.2.1.2 ?128.2.7.2
?? ??? ?255.255.0.0
?? ??? ?私有:
?? ??? ?172.16.0.0 - 172.31.255.255
?? ?C類:?? ?中小規模型網絡
?? ??? ?192.0.0.0 - 223.255.255.255
?? ??? ?255.255.255.0
?? ??? ?私有:
?? ??? ?192.168.0.0 - 192.168.255.255
?? ??? ?靜態路由
?? ??? ?192.168.0.0
?? ??? ?192.168.0.1 ?網關
?? ??? ?192.168.0.255?
?? ?D類:?? ?組播和廣播(廣播:所有用戶都能傳播,組播:某個小范圍組內能傳播)
? ? ? ? ? ? ?(無子網掩碼)
?? ??? ?224.0.0.0 - 239.255.255.255
?? ??? ?192.168.0.255 == ?255.255.255.255
?? ??? ?235.1.2.3
?? ??? ?192.168.1.0?
?? ??? ?192.168.0.1 ? 網關
?? ??? ?192.168.1.255 廣播?
?? ?E類:?? ?實驗
????????????(無子網掩碼)
?? ??? ?240.0.0.0 - 255.255.255.255
子網掩碼:1代表網絡部分,0代表主機部分
C 類網絡:
? ???ip地址的前三組是網絡地址,第四組是主機地址。
?? ?二進制的最高位必須是: 110xxxxx開頭
?? ?十進制表示范圍: 192.0.0.0 -223.255.255.255
?? ?默認網絡掩碼: ? 255.255.255.0
?? ?網絡個數: 2^24 個 約 209 萬個
?? ?主機個數: 2^8 ?個 254 個+2 --> 1個是網關(網絡地址.0 的下一個地址.1)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 另1個是廣播(.255最后一個地址)
?? ?私有地址: 192.168.x.x 局域網地址。
網絡接口(端口+ip -->?找到進程+找到主機)
1、socket ?套接字 --> BSD socket --> 用于網絡通信的一組接口函數。socket api ?application interface --> 進程到進程 --> 實現主機到主機通信
2、ip+port 地址+端口 --> 地址用來識別主機
?? ??? ??? ??? ??? ??? ? ? ? 端口用來識別應用程序
?? ??? ? ?port分為TCP port / UDP port ?范圍都是: 1-65535(2^16,兩個byte)
?? ??? ? ?約定1000 以內的端口為系統使用。
網絡字節序
--> 大端排序(高位數據放在高地址處)(高地址:值較大的地址)
--> 主機 --> 小端(高位數據放在低地址處)(從小往大走)
數字轉換函數:
? ? #include <arpa/inet.h>
?? ?主機轉網絡:uint32_t htonl(uint32_t hostlong);
?? ?ipv4 192.168.0.1 1~65535
?? ??? ??? ??? ?uint16_t htons(uint16_t hostshort);
?? ?網絡轉主機:host to net long?
?? ??? ??? ??? ?net to host?
?? ??? ??? ??? ?uint32_t ntohl(uint32_t netlong);? ?//對應16位轉換與32位轉換
?? ??? ??? ??? ?uint16_t ntohs(uint16_t netshort);
? ? 主機轉網絡:in_addr_t inet_addr(const char *cp);
? ? ? ? inet_addr("192.168.1.20");
? ? ? ? 網絡轉主機:char *inet_ntoa(struct in_addr in);
字符串轉換函數:
?? ?#include <sys/socket.h>
?? ?#include <netinet/in.h>
?? ?#include <arpa/inet.h>
?? ?主機轉網絡:in_addr_t inet_addr(const char *cp);
?? ? cli.sin_addr
?? ?inet_addr("192.168.1.20");
?? ?網絡轉主機:char *inet_ntoa(struct in_addr in);
收發數據(UDP)
UDP:半雙工,同一時刻要么收要么發
1、模式 ?C/S 模式 ?--> 服務器/客戶端模型(client/server)
server:socket()-->bind()--->listen()-->accept()-->recv()-->close()?
? ? ? ? ? ?創建套接字-->關聯接口地址-->-->收、發-->關閉
client:socket()-->connect()-->send()-->close();
? ? ? ? ? ? 創建套接字-->連接(客戶端可以不需要)-->收、發-->關閉
socket()
int socket(int domain, int type, int protocol);
功能:程序向內核提出創建一個基于內存的套接字描述符
參數:domain ?地址族,PF_INET(協議族) == AF_INET(地址族,IPv4) ==>互聯網程序
?? ??? ??? ??? ??? ? ?PF_UNIX == AF_UNIX ==>單機程序
?? ? ?type ? ?套接字類型:
?? ? ??? ??? ? ?SOCK_STREAM ?流式套接字 ===》TCP ??
?? ??? ??? ? ?SOCK_DGRAM ? 用戶數據報套接字===>UDP
?? ??? ??? ? ?SOCK_RAW ? ? 原始套接字 ?===》IP
?? ? ?protocol 協議 --> 0 表示自動適應應用層協議。
返回值:成功 返回申請的套接字id
?? ??? ?失敗 ?-1;
bind()
2、int bind(int sockfd, struct sockaddr *my_addr,?
? ? ? ? ? ? ?socklen_t addrlen);
功能:如果該函數在服務器端調用,則表示將參數1相關
?? ? ?的文件描述符文件與參數2 指定的接口地址關聯,
?? ? ?用于從該接口接受數據。
?? ? ?如果該函數在客戶端調用,則表示要將數據從
?? ? ?參數1所在的描述符中取出并從參數2所在的接口
?? ? ?設備上發送出去。
?? ? ?注意:如果是客戶端,則該函數可以省略,由默認
?? ? ? ? ? ?接口發送數據。
參數:sockfd 之前通過socket函數創建的文件描述符,套接字id
?? ? ?my_addr 是物理接口的結構體指針。表示該接口的信息。
?? ? ?struct sockaddr ? ? ?通用地址結構
?? ? ?{
?? ??? ? ?u_short sa_family; ?地址族
?? ??? ? ?char sa_data[14]; ? 地址信息
?? ? ?};
?? ? ?轉換成網絡地址結構如下:
?? ? ?struct _sockaddr_in ? ?///網絡地址結構
?? ? ?{
?? ??? ? ?u_short ?? ??? ? ?sin_family; 地址族
?? ??? ? ?u_short ?? ??? ? ?sin_port; ? ///地址端口
?? ??? ? ?struct in_addr ?sin_addr; ? ///地址IP
?? ??? ? ?char ?? ??? ??? ? ?sin_zero[8]; 占位
?? ? ?};
?? ? ?struct in_addr
?? ? ?{
?? ??? ? ?in_addr_t s_addr;
?? ? ?}
?? ? ?socklen_t addrlen: 參數2 的長度。
返回值:成功 ?0
? ? ? ? ? ? ?失敗 ?-1;
bind傳參要進行強轉,在實際使用中,struct sockaddr過于底層,不方便處理,而struct sockaddr_in專門用于IPv4地址,所以一般用struct sockaddr_in來定義
#typedef struct sockaddr * (SA);struct sockaddr_in ser;
int ret = bind(sockfd,(SA)&ser,sizeof(ser));
一般bind的操作為:
struct sockaddr_in ser,cli;
bzero(&ser,sizeof(ser));
bzero(&cli,sizeof(cli));
// 大小端轉化 host to net short
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.203.128");
int ret = bind(sockfd,(SA)&ser,sizeof(ser));
if(-1 == ret)
{perror("bind");exit(1);
}
接收函數/發送函數
??read()/write () ? ///通用文件讀寫,可以操作套接字。
??recv(,0) /send(,0) ? ? ?///TCP 常用套機字讀寫
??recvfrom()/sendto() ///UDP 常用套接字讀寫
ssize_t recv(int sockfd, void *buf, size_t len,
? ? ? ? ? ? ?int flags);
功能:從指定的sockfd套接字中以flags方式獲取長度
?? ? ?為len字節的數據到指定的buff內存中。
參數:sockfd ?
?? ??? ?如果服務器則是accept的返回值的新fd
?? ??? ?如果客戶端則是socket的返回值舊fd
?? ? ?buff 用來存儲數據的本地內存,一般是數組或者
?? ? ?動態內存。
?? ? ?len 要獲取的數據長度
?? ? ?flags 獲取數據的方式,0 表示阻塞接受。
返回值:成功 表示接受的數據長度,一般小于等于len
?? ??? ?失敗 ?-1;
close()
5、close() ?===>關閉指定的套接字id;
注意事項:
服務器:
需要先接收客戶端的地址(recvfrom),不然無法發送數據
typedef struct sockaddr *(SA);
socklen_t cli=sizeof(cli);
recvfrom(sockfd,buf_r,sizeof(buf_r),0,(SA)&cli,len_cli);
客戶端:
需要空發一下讓服務器拿到(對于收發先后沒有太大要求,recvfrom具有讀阻塞的作用)
char buf[128];
sendto(sockfd,buf,sizeof(buf),0,(SA)&ser,sizeof(ser));
客戶端recvfrom不需要最后兩個參數可以是NULL,因為本來就有父進程的端口號和ip
recvfrom(sockfd,buf_r,sizeof(buf_r),0,NULL,NULL);