1. 创建原始套接字
注意:原始套接字要超级用户才能使用。
调用socket函数,即可创建原始套接字。参数需要注意变更:
int socket(AF_INET,SOCK_RAW,protocol)
int socket(AF_PACKET,SOCK_RAW,protocol)
2. 发送消息
调用sendto可以发送信息
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
3. 接收消息
在下列情况下,内核会将接收到的IP数据报文传递给原始套接字
a. 接收到的TCP/UDP不会传递到任何套接字
b. ICMP分组会在内核处理完其中的ICMP消息后,传递到原始套接字
c. IGMP分组同上
d. 内核不认识其协议字段的IP数据包
接收消息函数
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
4. 简单示例,实现原始套接字发送数据
可以通过wireshark分析数据包内容。
int main(int argc, char *argv){
int rv;
int sockfd;
char buf[100] = "test! socket";
struct sockaddr_in raw;
int len;
sockfd = socket(AF_INET, SOCK_RAW, 0x5a);
bzero(&raw, sizeof(struct sockaddr_in));
raw.sin_family = AF_INET;
raw.sin_addr.s_addr = inet_addr("192.168.1.109");
len = sizeof(struct sockaddr_in);
rv = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&raw,len);
if(rv < 0){
perror("sendto error");
return -1;
}
printf("sendto over.\n");
return 0;
}
5. 简要分析数据帧格式
以太网head:
a. 6bytes目的mac地址
b. 6bytes源mac地址
c. 2bytes类型,协议号:0800IP数据报,0806ARP,8035RARP
IP层数据:
a. 20bytes头部
b. ICMP协议可以用于检测网络是否通畅,比如ping
c. IGMP组播报文