网络地址分类(32位网络地址)
A类地址:第一个字节为网络地址,其他3个字节主机地址,第一字节的最高位固定为0
从1.0.0.1------126.255.255.255
B类地址:第一字节和第二字节为网络地址,其他2个字节为主机地址,第一字节前两位固定为10
从128.0.0.1---191.255.255.255
C类地址:前三个字节为网络地址,最后一个字节是主机地址,第一字节的前三位固定为110
从192.0.0.1----223.255.255.255
D类地址:组播地址
不分网络地址和主机地址,第一字节的前四位固定为1110
224.0.0.1-----239.255.255.255
注意几点:
1、192.168.1.255为广播地址,任何主机都是不能使用的。
2、每一个网络地址都能组成一个小型的局域网。
3、127.0.0.1测试tcp,udp网络时使用的内部回环网络
几种常见的网络分包格式
一、 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和端口号。
二、 udp数据包格式:
跟tcp差不多,只是传输层的协议改成了udp,面向不链接。
Sendto的倒数第二个参数填放了目标主机的ip及端口等信息
几种常见的网络分包格式
三、 广播udp数据包格式:
与udp数据包有两个地方的区别:
1、 分别是mac地址为FF :FF: FF: FF:FF:FF整个四十八位全为1
2、 在网络层目标ip地址为:192.168.1.255
四、 组播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)//2、、、、、、绑定本机的ip地址 perror("bind() error! "); 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! "); 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! "); // printf("%d ",n); bzero(buf1,20); recvfrom(socketfd,buf1,20,0,(struct sockaddr *)&caddr,&s); printf("%s",buf1); } close(socketfd);//、、、4.关闭socketfd }