相关API
创建套接字
#include <sys/types.h>
#include <sys/socket.h>
/**
* [socket 创建套接字]
* @param domain [由于需要创建原始套接字(基于链路层创建),需要选择通信域为: AF_PACKET]
* @param type [使用的是SOCK_RAW表示创建的是原始套接字文件]
* @param protocol [
* 指定可以接收或发送的数据包类型
* ETH_P_IP: IP数据包
ETH_P_ARP: ARP数据包
ETH_P_ALL: 任何协议类型的数据包
* ]
* @return [成功返回一个大于0的文件描述符,表示网络数据链路层的套接字文件;
失败返回-1,且修改errno的值]
*/
int socket(int domain, int type, int protocol);
接收
#include <sys/types.h>
#include <sys/socket.h>
/**
* [recvfrom 接收数据]
* @param sockfd [sockfd套接字文件描述符]
* @param buf [buf指针指向的空间用存储接收到的数据]
* @param len [len表示参数2指向空间的大小]
* @param flags [flags表示数据接收的方式,常用0表示阻塞接收]
* @param src_addr [src_addr指向的空间用来返回对端的IP地址和端口号,如果不关心则使用NULL]
* @param addrlen [addrlen指针指向的空间用来返回参数5指向对端空间的大小]
* @return [成功返回接收数据的字节数,失败返回-1且修改errno的值]
*/
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
实例
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
int main()
{
int ret;
int sockfd;
unsigned char buf[1024];
char dest_mac[18];
char src_mac[18];
unsigned short type;
/* 创建原始套接字文件:基于链路层,可用于任意协议数据的收发 */
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(sockfd == -1)
{
perror("socket");
return -1;
}
//循环接收
while(1)
{
//sleep(1);
ret = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
if (ret == -1)
{
perror("recvfrom");
return -1;
}
/* 解析数据:以太网数据:目的mac和源mac地址 */
sprintf(dest_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
/* 解析得到报文的类型:由于是网络字节序数据,所以需要转换为主机字节序 */
type = htons(*((unsigned short *)(buf + 12)));
if (type == 0x0806)
{
printf(" ARP\n");
/* 在进行ARP请求的时候需要添加IP地址,在做出ARP应答产生 */
}
else if (type == 0x8035)
{
printf(" RARP\n");
/* 在进行RARP请求的时候需要添加MAC地址,在做出RARP应答产生 */
}
else if (type == 0x0800)
{
printf("IP Data:");
/* 解析IP报文数据:源IP和目的IP、UDP报文或者TCP报文 */
unsigned char *ip_buf = buf + 14;/* 14字节是以太网头: */
/* 输出源mac -> 目的mac */
//printf("%s -> %s\n", src_mac, dest_mac);
/* 解析首部长度 */
unsigned int ip_head_len = ((*ip_buf) & 0xf) * 4;
//printf("%d\n", ip_head_len);
/* 解析IP报文中的源IP和目的IP */
char src_ip[16];
char dest_ip[16];
inet_ntop(AF_INET, ip_buf + 12, src_ip, sizeof(src_ip));
inet_ntop(AF_INET, ip_buf + 16, dest_ip, sizeof(dest_ip));
//printf("\t%s -> %s\n", src_ip, dest_ip);
/* 解析IP报文的类型 */
unsigned char ip_type = *(ip_buf + 9);
if ( ip_type == 1 )
{
printf("\t\tICMP");
}
else if ( ip_type == 2 )
{
printf("\t\tIGMP");
}
else if ( ip_type == 6 )
{
printf("\t\tTCP Data:\n");
unsigned char *tcp_buf = ip_buf + ip_head_len;
/* 解析TCP的源端口和目的端口 */
unsigned short src_port = ntohs(*(unsigned short *)tcp_buf);
unsigned short dest_port = ntohs(*(unsigned short *)(tcp_buf + 2));
/* 解析数据内容 */
/* tcp头部长度 */
unsigned int tcp_head_len = ((*(tcp_buf + 12) >> 4) & 0x0f) * 4;
printf("tcp:%s:%d -> %s:%d : %s\n", src_ip, src_port, dest_ip, dest_port, tcp_buf + tcp_head_len);
}
else if ( ip_type == 17 )
{
unsigned char *udp_buf = ip_buf + ip_head_len;/* 跳转到UDP报文起始地址 */
/* 解析UDP的源端口和目的端口 */
unsigned short src_port = ntohs(*(unsigned short *)udp_buf);
unsigned short dest_port = ntohs(*(unsigned short *)(udp_buf + 2));
/* 解析得到udp数据内容 */
//printf("%s\n", udp_buf+8);
printf("%s -> %s\n", src_mac, dest_mac);
printf("%s:%d -> %s:%d : %s\n", src_ip, src_port, dest_ip, dest_port, udp_buf + 8);
}
}
else
{
}
}
}
网友评论