/*
________________________________________________________ //4Byte
|____type_____|____code_____|_____________chksum_________| //4Byte
|_________data______________|_____________data___________|
| |
| |
*/
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<arpa/inet.h> 4 #include<sys/socket.h> 5 #include<fcntl.h> 6 #include<unistd.h> 7 #include<netdb.h> 8 9 int main(){ 10 int s = socket(PF_INET,SOCK_RAW,1);//创建//原始套接字可以读写内核没有处理的IP数据包,而流式套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据 11 // printf("--%d--\n",s); 12 if (s <= 0){ 13 perror("socket erro"); 14 exit(0); 15 } 16 typedef struct{ //ICMP请求头部 17 uint8_t type; 18 uint8_t code; 19 uint16_t chksum; 20 uint32_t data; 21 }icmp_hdr_t; 22 23 icmp_hdr_t pckt; 24 25 pckt.type=8; //1Byte 26 pckt.code=0; //1Byte 27 pckt.chksum=0xfff7;//2Byte 28 pckt.data=0; //4Byte 29 30 struct sockaddr_in addr;//目的地的信息 31 32 addr.sin_family=AF_INET; 33 addr.sin_port=0; 34 addr.sin_addr.s_addr=inet_addr("8.8.8.8");//Ping的目的地址 35 //addr.sin_zero[]="";
36 int actionSendResult=sendto(s,&pckt,sizeof(pckt),0,(struct sockaddr *)&addr,sizeof(addr)); 37 38 if(actionSendResult<=0){ 39 perror("ping erro"); 40 exit(0); 41 } 42 unsigned int resAddressSize; 43 unsigned char res[100]=""; 44 struct sockaddr resAddress; 45 //printf("%u\n",resAddressSize);
46 int ressponse=recvfrom(s,res,sizeof(res),0,&resAddress,&resAddressSize); 47 if(ressponse>0){ 48 printf("message is %d bytes long, and looks like this :\n",ressponse); 49 for(int i=0;i<ressponse;i++) printf("%02hhx ",res[i]); 50 printf("\n"); 51 //exit(0); 52 53 }else{ 54 perror("ressponse error"); 55 exit(0); 56 } 57 printf("resAddressSize:%u\n",resAddressSize); 58 struct sockaddr_in * temp; 59 temp=(struct sockaddr_in *)&resAddress; 60 printf("protocol:%d\n",temp->sin_family); 61 printf("port:%d\n",temp->sin_port); 62 return 0; 63 }
1.从下图得
发送:ICMP-->IP-->Ethernet
2.接收:Ethenet-->IP-->ICMP
recvfrom()直接从Ethenet接收内容
3.recvfrom()接收任意ICMP数据
4.WireShark没有ICMP协议的数据包,但程序有返回信息,说明recvfrom并未操作在ICMP之上,而是接收数据链路层处理完的数据(原始套接字可以读写内核没有处理的IP数据包,而流式套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据)
目的地址不可达,recvfrom()为什么会接收到“消息”,哪里来的消息?什么协议?
网络层(IP)无法发送?