1. 目的
不同主機,進程間通信。
2. 解決的問題
? ? ?1). 主機與主機之間物理層面必須互聯互通。
2.) 進程與進程在軟件層面必須互聯互通。
IP地址:計算機的軟件地址,用來標識計算機設備
MAC地址:計算機的硬件地址(固定)
網絡的端口號:標記同一主機上的不同網絡進程
?3. 網絡協議
網絡通信標準。
OSI七層模型:開放系統互聯模型(open system interconnect)
理論模型:
不同體系結構設備間,網絡通信的通信標準。
? ??? ?應用層:要傳輸的數據信息,如文件傳輸,電子郵件等
表示層:數據加密,解密操作,壓縮,解壓縮
會話層:建立數據傳輸通道, ? ---》會話
傳輸層:傳輸的方式 ?UDP ?TCP ? 端口號
網絡層:實現數據路由,路徑規劃 ? ?路由器 ?ip
數據鏈路層:封裝成幀,點對點通信(局域網內通信),差錯檢測 ? 交換機 ?ARP
物理層:定義物理設備標準、電氣特性,比如網線,光纖等傳輸介質 ? 比特流 ?bit ?0 1
TCP/IP模型:應用模型
五層:
應用層:
HTTP:超文本傳輸協議
HTTPS:超文本傳輸協議(SSL加密算法)
FTP:文件傳輸協議(TCP)
TFTP:簡單文件傳輸協議(UDP)
MQTT:消息隊列遙測傳輸(物聯網協議)
DNS:域名解析服務(www.baidu.com---》IP地址)
傳輸層:
TCP :傳輸控制協議
UDP:用戶數據報協議
網絡層:
IP協議:?IPv4? ? ? ? ?IPv6
數據鏈路層:
ARP : 地址解析協議
物理層:
四層:
應用層? ? ?傳輸層? ? ?網絡層? ? ? ? ?網絡接口層:
4. IP協議
? ? 網絡層:
IP協議
192.168.1.128
IPv4 ? ?32位
IPv6 ? ?128位
192.168.1.140 ?? ??? ?(用戶表示形式) ? 點分十進制 ??
11000000 10101000 00000000 01000011?? ?(計算機存儲形式) 32bits
IP地址 = 網絡位 + 主機位?
192.168.0.121/24
24:網絡位的位數
網絡位:該IP地址位于哪個網段(局域網)內
主機位:這個網段(局域網)第幾臺主機
?? ??? ?子網掩碼:
如:255.255.255.0
11111111.11111111.11111111.00000000
用來區分IP地址的網絡位和主機位,搭配IP地址使用。
子網掩碼是1的部分對應IP地址的網絡位
子網掩碼是0的部分對應IP地址的主機位
?? ??? ?192.168.1.0
網段號:
IP地址網絡位不變,主機位全為0,則為該IP地址的網段號
192.168.1.3
255.255.0.0
192.168.0.0
位于
192.168.1.0 網段內(網段內的IP能直接通信)
192.168.1.3
255.0.0.0
?? ??? ?廣播號:
192.168.1.255
IP地址網絡位不變,主機位全為1,則為該IP地址的廣播號
192.168.1.3
255.255.255.0
廣播號:
192.168.1.255(向廣播號發送信息,所有局域網內IP都能收到此信息)
feiQ VNC
192.168.1.255
網關地址:
192.168.1.1
IP地址的劃分:
(1)A類地址:
范圍:1.0.0.0 - 126.255.255.255
子網掩碼:255.0.0.0 ? ? ? ? ?126*2^24 ? ? ? ?
用于管理大規模網絡
私有IP地址:10.0.0.0 - 10.255.255.255
127.0.0.0 ? 回環地址
(2)B類地址:
范圍:128.0.0.0 - 191.255.255.255
子網掩碼:255.255.0.0 ? ? ? ? 2^16
管理大中規模網絡
私有IP地址:172.16.0.0 - 172.31.255.255
(3)C類地址:
范圍:192.0.0.0 - 223.255.255.255
子網掩碼:255.255.255.0 ? ? ? ?2^8
管理中小規模網絡
私有IP地址:192.168.0.0 - 192.168.255.255
(4)D類地址:
224.0.0.0 - 239.255.255.255
組播和廣播使用
(5)E類地址:
240.0.0.0 - 255.255.255.254
用來進行實驗
?? ??? ?公有IP:由電信公司直接分配,并需要付費的IP地址, 可以直接訪問internet
私有IP:不能直接訪問internet的ip地址
節省ip地址
5. 網絡端口號
? ? 端口號:16位的整形數據(unsigned short)0-65535
端口號功能:標記同一主機上的不同網絡進程
? ? 分類:
1)任何TCP/IP實現所提供的服務都用1-1023之間的端口號。
http : 80
FTP: 20/21
TFPT: 69
HTTPS: 443
2)端口號從1024-49151是被注冊的端口號,被IANA指定為特殊服務使用。
MQTT:1883/8883
3)從49152-65535是動態或私有端口號。
6.網絡配置
? ?1. ?ping ?ip地址/域名
查看當前主機和IP/域名所對應的這臺主機網絡是否聯通
ping www.baidu.com
? ?2. ifconfig?
在Linux查看當前主機的IP地址
ipconfig
在Windows上查看當前主機的IP地址
? ?3. 網絡配置
1)虛擬機--》設置--》網絡適配器---》橋接模式
2)編輯--》虛擬網絡編輯器--》更改設置--》VMnet0---》橋接至--》當前PC正在上網的網卡上--》應用--》確定
3)修改網絡配置文件
sudo vim /etc/network/interfaces
?????????????auto lo
iface lo inet loopback
? ? ? ? ? ? ?auto ens33?
iface ens33 inet dhcp
? ? ? ? 4)重啟網絡服務
sudo /etc/init.d/networking restart
5) 測試
ping www.baidu.com
7. 網絡協議--UDP
? ? ?UDP:傳輸層
用戶數據報協議(User Datagram Protocol)
? ? ?1)網絡編程模型
B/S模型:browser/server(瀏覽器/服務器)
1. 客戶端是通用的客戶端(瀏覽器)
2. 一般只做服務器開發
3. 客戶端要加載的數據均來自服務器
C/S模型:client/server(客戶端/服務端)
1. 客戶端是一個專用的客戶端
2. 服務器和客戶端都需開發
3. 客戶端可保存資源,本地加載,無需所有數據都請求服務器
? ? ?2)UDP編程流程
? ? ? ? ? ?套接字:文件描述符?, 網絡通信時,應用層可操作的端口。
?#include <sys/types.h> ? ? ? ? ?/* See NOTES */
#include <sys/socket.h>
? ? ? ?int socket(int domain, int type, int protocol);
功能:創建通信的套接字
參數:
domain:網絡層使用什么協議族
AF_INET:IPv4
AF_INET6:IPv6
type:規定傳輸層的協議
SOCK_DGRAM : UDP協議
SOCK_STREAM:TCP協議
SOCK_RAW :原始套接字
protocol :0 按照默認協議方式創建
返回值:
成功:套接字
失敗:-1
? ? ? ?ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
功能:向網絡套接字發送數據
參數:
sockfd:套接字
buf: 要發送的數據的首地址
len:要發送的字節數
flags: 0:按照默認方式發送
dest_addr:接收方的地址信息(IP+端口號)
addrlen:接收方地址的大小
返回值:
成功:實際發送的字節數
失敗:-1
? ? ? ?man 7 ip
struct sockaddr_in {
sa_family_t ? ?sin_family; /* address family: AF_INET */
in_port_t ? ? ?sin_port; ? /* port in network byte order */
struct in_addr sin_addr; ? /* internet address */
};
? ? ? ? ? ?/* Internet address. */
struct in_addr {
uint32_t ? ? ? s_addr; ? ? /* address in network byte order */
};
網絡字節序:大端 ? ? ? ? ? ? ? ?network
主機字節序:小端 ?50000 ? host
0x1234
小端:0x34
0x12
大端:
0x12
0x34
uint32_t htonl(uint32_t hostlong); ? ? ? ? ?主機轉網絡
uint16_t htons(uint16_t hostshort); ? ? ? ? 主機轉網絡
uint32_t ntohl(uint32_t netlong); ? ? ? ? ? 網絡轉主機
uint16_t ntohs(uint16_t netshort); ? ? ? ? ?網絡轉主機
?in_addr_t inet_addr(const char *cp);
功能:
將字符串IP地址轉換成二進制IP地址形式
?char *inet_ntoa(struct in_addr in);
功能:
將二進制ip轉換成字符串
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:綁定自己的IP地址和端口號
參數:
sockfd:套接字
addr:需要綁定的地址
addrlen:地址大小
返回值:
成功:0
失敗:-1
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
功能:從套接字上接收數據
參數:
sockfd:套接字
buf:存放接收數據的內存首地址
len:希望接收的字節數
flags:0 :按照默認方式接收(阻塞)
src_addr:發送方的地址信息
addrlen:發送發地址的指針
功能:
成功:實際接收到的字節數
失敗:-1
利用UDP實現通信
客戶端程序
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>int main()
{pid_t pid = fork();if(pid > 0){int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd < 0){perror("socket error:");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50001);seraddr.sin_addr.s_addr = inet_addr("192.168.0.175");char buff[1024] = {0};while(1){scanf("%s",buff);ssize_t cnt = sendto(sockfd,buff,strlen(buff),0,(struct sockaddr *)&seraddr,sizeof(seraddr));if(cnt < 0){perror("send error:");return -1;}printf("cnt = %ld\n",cnt);}close(sockfd);}else if(pid == 0){int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd < 0){perror("socket error:");return -1;}struct sockaddr_in cliaddr;cliaddr.sin_family = AF_INET;cliaddr.sin_port = htons(50000);cliaddr.sin_addr.s_addr = inet_addr("192.168.0.175");int ret = bind(sockfd,(struct sockaddr *)&cliaddr,sizeof(cliaddr));if(ret < 0){perror("bind error:");return -1;}char buff[1024] = {0};while(1){memset(buff, 0, sizeof(buff));ssize_t cnt = recvfrom(sockfd,buff,sizeof(buff),0,NULL,NULL);if(cnt <= 0){break;}printf("cnt = %ld,server->client = %s\n",cnt,buff);}close(sockfd);}return 0;
}
服務端程序
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>int main()
{pid_t pid = fork();if(pid > 0){int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd < 0){perror("socket error:");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50001);seraddr.sin_addr.s_addr = inet_addr("192.168.0.175");int ret = bind(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));if(ret < 0){perror("bind error:");return -1;}char buff[1024] = {0};while(1){memset(buff, 0, sizeof(buff));ssize_t cnt = recvfrom(sockfd,buff,sizeof(buff),0,NULL,NULL);if(cnt <= 0){break;}printf("cnt = %ld,client->server = %s\n",cnt,buff);}close(sockfd);}else if(pid == 0){int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd < 0){perror("socket error:");return -1;}struct sockaddr_in cliaddr;cliaddr.sin_family = AF_INET;cliaddr.sin_port = htons(50000);cliaddr.sin_addr.s_addr = inet_addr("192.168.0.175");char buff[1024] = {0};while(1){scanf("%s",buff);ssize_t cnt = sendto(sockfd,buff,strlen(buff),0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));if(cnt < 0){perror("send error:");return -1;}printf("cnt = %ld\n",cnt);}close(sockfd);}return 0;
}