網絡地址分類(32位網絡地址)編程
A類地址:第一個字節爲網絡地址,其餘3個字節主機地址,第一字節的最高位固定爲0服務器
從1.0.0.1------126.255.255.255網絡
B類地址:第一字節和第二字節爲網絡地址,其餘2個字節爲主機地址,第一字節前兩位固定爲10socket
從128.0.0.1---191.255.255.255tcp
C類地址:前三個字節爲網絡地址,最後一個字節是主機地址,第一字節的前三位固定爲110函數
從192.0.0.1----223.255.255.255測試
D類地址:組播地址spa
不分網絡地址和主機地址,第一字節的前四位固定爲11103d
224.0.0.1-----239.255.255.255code
注意幾點:
1、192.168.1.255爲廣播地址,任何主機都是不能使用的。
2、每個網絡地址都能組成一個小型的局域網。
3、127.0.0.1測試tcp,udp網絡時使用的內部迴環網絡
幾種常見的網絡分包格式
1、 tcp數據包格式:
Ethernet header:網絡物理接口層(存放了網卡的MAC地址,共48位)
Ip header:網絡層,存放了目標主機的ip地址,源主機的ip地址
TCP:傳輸層,存放了目標主機的port號和源主機的port號。這層肯定傳輸是否可靠
Ethernet trailer:對傳輸的數據進行CRC校驗
發送過程:應用層—>加個應用層頭-à加個tcp頭---》加個ip頭---》加個ethernet 頭(指定mac地址)---》最後對數據進行CRC校驗。
接收過程:反方向砍掉各類各樣的頭,先進行CRC校驗---》驗證MAC地址,若是匹配,則將其砍掉---》驗證主機ip地址、匹配,將其砍掉----》驗證tcp的port,匹配將其砍掉---》最後只剩下數據了。
Accept的第二個參數填放了目標主機的ip和端口號。
2、 udp數據包格式:
跟tcp差很少,只是傳輸層的協議改爲了udp,面向不連接。
Sendto的倒數第二個參數填放了目標主機的ip及端口等信息
幾種常見的網絡分包格式
3、 廣播udp數據包格式:
與udp數據包有兩個地方的區別:
一、 分別是mac地址爲FF :FF: FF: FF:FF:FF整個四十八位全爲1
二、 在網絡層目標ip地址爲:192.168.1.255
4、 組播udp數據包格式:
與廣播udp數據包格式的區別主要在mac:組播數據包的mac目標地址爲:[0 00500]前面爲高25位,低23位爲目標ip的低23位,這樣的話,只要目標ip沒有加入到組播,mac地址首先就沒法匹配,這樣大大提升了數據的傳輸效率,不用每次都須要匹配到udp 的傳輸層才能判斷出是否要發送數據。
UDP的通訊的範例 編程步驟: 服務器(收數據): 1、建立socket(socket())獲得socketfd 2、綁定本機ip(bind())通常綁定宏ip 3、先接受數據獲得對方的ip和port(recvfrom()) 4、發送數據(sendto()) 5、關閉socketfd(close()) (發送數據) 1、建立socket(socket())獲得socketfd 2、初始化對方主機的ip和端口號 3、發送數據(sendto)倒數第二參數爲對方的ip和port號 4、接受數據 5、關閉socket(close()) 服務器: #include<stdio.h> #include<netinet/in.h> #include<stdlib.h> #include<string.h> #include <sys/types.h> #include <sys/socket.h> #include<pthread.h> #include<strings.h> int main() { int socketfd = socket(AF_INET,SOCK_DGRAM,0);//、、、、1.建立udp套接字socket獲得socketfd struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(6000); //此處可使用宏ip(=htonl(INADDR_ANY))該宏ip爲一個整型數z轉化爲二進制L==long saddr.sin_addr.s_addr = inet_addr("192.168.193.2"); if(bind(socketfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr_in))<0)//二、、、、、、綁定本機的ip地址 perror("bind() error!\n"); struct sockaddr_in caddr; int s = sizeof(struct sockaddr); char buf[20],buf1[20]; int n; while(1)//、、、、、、、、、、、、、、、、、、、、、、、、3.收發數據 { bzero(buf,20); //scanf("%s",buf); if(n = recvfrom(socketfd,buf,20,0,(struct sockaddr *)&caddr,&s)<0)//recvfrom的倒數第二個參數爲對方的ip和端口號,recvfrom函數自動獲取,所以sendto中的地址就填該結構體。 perror("send() error!\n"); printf("%s",buf); fgets(buf1,20,stdin); sendto(socketfd,buf1,strlen(buf),0,(struct sockaddr *)&caddr,s); } close(socketfd);//、、、、、、、、、、4.關閉套接字socketfd } 客戶端: #include<stdio.h> #include<netinet/in.h> #include<stdlib.h> #include<string.h> #include <sys/types.h> #include <sys/socket.h> #include<pthread.h> #include<strings.h> int main() { int socketfd = socket(AF_INET,SOCK_DGRAM,0);//、、、、、、、1.建立udp套接字獲得socketfd文件描述符 struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(6000); saddr.sin_addr.s_addr = inet_addr("192.168.193.2");//、、、2.初始化結構體sockaddr_in 目標主機的ip,sendto的倒數第二個參數 struct sockaddr_in caddr; int s = sizeof(struct sockaddr); char buf[20],buf1[20]; int n; while(1)//、、、、3.發送接收數據. { //bzero(buf,20); fgets(buf,20,stdin); if(n = sendto(socketfd,buf,strlen(buf),0,(struct sockaddr *)&saddr,s)<0) perror("recv() error!\n"); // printf("%d\n",n); bzero(buf1,20); recvfrom(socketfd,buf1,20,0,(struct sockaddr *)&caddr,&s); printf("%s",buf1); } close(socketfd);//、、、4.關閉socketfd }