我正在编写 NETLINK xfrm 套接字编程来创建 ESP 通信的关联和策略。将数据发送到内核
sockfd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_XFRM);
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sckbuff, sizeof(sckbuff));
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &sckbuff, sizeof(sckbuff));
bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_nl));
...
memset(&msg, 0, sizeof(struct msghdr));
msg.msg_name = (void *)&(addr);
msg.msg_namelen = sizeof(addr);
...
memset(&iov, 0, sizeof(struct iovec));
iov.iov_base = (void *)netlink_req;
iov.iov_len = netlink_req->nlmsg_len;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(sockfd, &msg, 0);
并接收来自内核的响应
while(true)
{
...
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
select(sockfd+1, &readfds, NULL, NULL, NULL);
read_len = recvmsg(sockfd, &msg, MSG_PEEK);
printf("Data received %d\n", read_len);
for (nh = (struct nlmsghdr *) buf;
NLMSG_OK (nh, read_len);
nh = NLMSG_NEXT (nh, read_len))
{
if (nh->nlmsg_type == NLMSG_DONE)
{
break;
}
else if (nh->nlmsg_type == NLMSG_ERROR)
{
...
}
...
}
}
...
如果recvmsg按顺序完成而没有
select
,则它是工作文件。
但是当我尝试发送多个请求并在另一个线程中使用
select
执行 sockfd
时,recvmsg
继续接收相同的消息并且永远不会停止。
我需要设置任何标志来响应停止连续循环或任何其他方式吗?
recvmsg()
,当使用 MSG_PEEK
标志调用时,会返回数据,但不会将其从套接字的接收队列中删除,从而导致下一个接收再次返回相同的数据。
删除标志(或在没有标志的情况下对相同大小执行第二次调用)以确保您收到以下消息。
我还强烈建议检查
select()
的返回以及更新后的集合(因为在这种情况下,select()
可以在没有可读套接字的情况下返回,例如,如果捕获到信号)。
我还想指出,在您当前的使用中,select()
并没有为您提供比普通阻塞 recvmsg()
调用更多的功能。