我在调用socket()时使用PF_PACKET和SOCK_RAW以及自定义协议来构建服务器/客户端软件
在客户端软件中,我以相同的方式创建套接字,只需从该套接字执行rcv即可获取数据
我的问题是我是否必须以与服务器相同的方式填写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);
所以这就是我在没有填充struct sockaddr_ll的情况下基本上在客户端接收数据的方法
对于服务器程序,我必须填写结构
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回复
答案 0 :(得分:1)
您应该使用
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);