基于socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL)),接收和发送数据软件,C++代码
时间: 2024-03-14 12:48:24 浏览: 187
以下是基于socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL))的接收和发送数据软件的C++代码示例:
```c++
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#define ETH_HDRLEN 14
using namespace std;
int main(int argc, char* argv[]) {
int sock_fd;
struct ifreq ifr;
char iface[] = "eth0"; // 设备名称
char buffer[ETH_FRAME_LEN];
struct sockaddr_in source, dest;
struct ethhdr* eth_hdr;
struct iphdr* ip_hdr;
struct tcphdr* tcp_hdr;
int data_len;
// 创建原始套接字
sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock_fd < 0) {
perror("Error creating socket");
return 1;
}
// 获取设备索引号
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)-1);
if (ioctl(sock_fd, SIOCGIFINDEX, &ifr) < 0) {
perror("Error getting interface index");
return 1;
}
// 将socket与设备绑定
struct sockaddr_ll socket_address;
memset(&socket_address, 0, sizeof(socket_address));
socket_address.sll_family = PF_PACKET;
socket_address.sll_ifindex = ifr.ifr_ifindex;
socket_address.sll_protocol = htons(ETH_P_ALL);
bind(sock_fd, (struct sockaddr*)&socket_address, sizeof(socket_address));
// 接收数据包
while (true) {
data_len = recvfrom(sock_fd, buffer, ETH_FRAME_LEN, 0, NULL, NULL);
if (data_len < 0) {
perror("Error receiving packet");
break;
}
// 解析数据包
eth_hdr = (struct ethhdr*)buffer;
if (ntohs(eth_hdr->h_proto) != ETH_P_IP) {
continue;
}
ip_hdr = (struct iphdr*)(buffer + ETH_HDRLEN);
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = ip_hdr->saddr;
memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = ip_hdr->daddr;
if (ip_hdr->protocol == IPPROTO_TCP) {
tcp_hdr = (struct tcphdr*)(buffer + ETH_HDRLEN + (ip_hdr->ihl * 4));
cout << inet_ntoa(source.sin_addr) << ":" << ntohs(tcp_hdr->source)
<< " -> " << inet_ntoa(dest.sin_addr) << ":" << ntohs(tcp_hdr->dest) << endl;
}
}
// 发送数据包
memset(buffer, 0, sizeof(buffer));
eth_hdr = (struct ethhdr*)buffer;
// 目标MAC地址
eth_hdr->h_dest[0] = 0x00;
eth_hdr->h_dest[1] = 0x11;
eth_hdr->h_dest[2] = 0x22;
eth_hdr->h_dest[3] = 0x33;
eth_hdr->h_dest[4] = 0x44;
eth_hdr->h_dest[5] = 0x55;
// 源MAC地址
eth_hdr->h_source[0] = 0x55;
eth_hdr->h_source[1] = 0x44;
eth_hdr->h_source[2] = 0x33;
eth_hdr->h_source[3] = 0x22;
eth_hdr->h_source[4] = 0x11;
eth_hdr->h_source[5] = 0x00;
// 协议类型
eth_hdr->h_proto = htons(ETH_P_IP);
// IP头
ip_hdr = (struct iphdr*)(buffer + ETH_HDRLEN);
ip_hdr->version = 4;
ip_hdr->ihl = 5;
ip_hdr->tos = 0;
ip_hdr->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
ip_hdr->id = htons(12345);
ip_hdr->frag_off = 0;
ip_hdr->ttl = 255;
ip_hdr->protocol = IPPROTO_TCP;
ip_hdr->check = 0;
ip_hdr->saddr = inet_addr("192.168.0.1");
ip_hdr->daddr = inet_addr("192.168.0.2");
// TCP头
tcp_hdr = (struct tcphdr*)(buffer + ETH_HDRLEN + (ip_hdr->ihl * 4));
tcp_hdr->source = htons(12345);
tcp_hdr->dest = htons(80);
tcp_hdr->seq = htonl(1);
tcp_hdr->ack_seq = 0;
tcp_hdr->doff = 5;
tcp_hdr->urg = 0;
tcp_hdr->ack = 0;
tcp_hdr->psh = 0;
tcp_hdr->rst = 0;
tcp_hdr->syn = 1;
tcp_hdr->fin = 0;
tcp_hdr->window = htons(1024);
tcp_hdr->check = 0;
tcp_hdr->urg_ptr = 0;
// 发送数据包
data_len = send(sock_fd, buffer, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct tcphdr), 0);
if (data_len < 0) {
perror("Error sending packet");
return 1;
}
close(sock_fd);
return 0;
}
```
该程序在基于socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL))的基础上,添加了发送数据包的功能。程序首先使用recvfrom函数接收数据包,并解析出IP、TCP头的源地址、目的地址、源端口、目的端口等信息进行输出。然后,程序构造了一个TCP SYN数据包,并使用send函数发送出去,实现了发送数据包的功能。
阅读全文
相关推荐


















