我正在使用PF_PACKET和SOCK_RAW构建服务器/客户端软件,并在调用socket()时使用自定义协议。
在客户端软件中,我以同样的方式创建套接字,并从该套接字执行get,然后获取数据
我的问题是,我是否必须像填写服务器一样填写sockaddr_ll结构,因为当我从客户端回复时,我获得的源MAC地址是一个奇怪的地址,例如11:11:00:00:00:00,当然这不是我客户端的MAC
有人知道这是怎么回事吗?打开插座
if ( (sckfd=socket(PF_PACKET, SOCK_RAW, htons(proto)))<0)
{
myError("socket");
}
这就是我接收数据的方式
n = recvfrom(sckfd, buffer, 2048, 0, NULL, NULL);
printf("%d bytes read\n",n);
这基本上就是我在不填充结构sockaddr_ll的情况下在客户端接收数据的方式
对于server Program,我必须填充结构
struct sockaddr_ll saddrll;
memset((void*)&saddrll, 0, sizeof(saddrll));
saddrll.sll_family = PF_PACKET;
saddrll.sll_ifindex = ifindex;
saddrll.sll_halen = ETH_ALEN;
memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);
我的问题是,我如图所示接收并如图所示发送,当我回复服务器调用服务器中用于发送的相同函数时,当我接收客户端回复时,我会得到什么: 11:11:00:00:00:00
发布于 2013-11-07 07:05:23
您可能应该使用
socket(AF_PACKET, SOCK_DGRAM, htons(proto)))
而不是SOCK_RAW套接字。通过SOCK_RAW,您可以发送/接收整个以太网帧,包括源和目的MAC地址。使用SOCK_DGRAM,内核将填充以太网头。
您可能希望将回复发送到与请求来自相同的地址,recvfrom()可以填充源地址;
struct sockaddr_ll src_addr;
socklen_t addr_len = sizeof src_addr;
n = recvfrom(sckfd, buffer, 2048, 0,
(struct sockaddr*)&src_addr, &addr_len);
现在你已经知道了源地址,所以把包发回给它:
...
sendto(sckfd, data, data_len, src_addr, addr_len);
如果你更需要使用SOCK_RAW,你也会收到以太网报头,所以只需从接收到的数据中复制出MAC地址,并在构建回复帧时交换它们。
对于一个SOCK_RAW套接字,你可以手工制作整个以太网帧,你不需要填写以太网地址,所以不需要下面的内容;
memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);
https://stackoverflow.com/questions/19816071
复制相似问题