recvmsg with select 在 NETLINK 套接字上

recvmsg with select on NETLINK socket

我正在编写 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)
    {
      ...
    }
    ...
  }
}
...

如果没有select.

按顺序完成recvmsg,则为工作文件

但是当我尝试发送多个请求并在另一个线程中使用 sockfd 执行 select 时,然后 recvmsg 继续接收相同的消息并且永不停止。

是否需要设置任何标志以响应停止连续循环或任何其他方式?

recvmsg(),当使用 MSG_PEEK 标志调用时,returns 数据但不会从套接字的接收队列中删除它,导致下一个接收 return再次读取相同的数据。

删除标志(或在没有它的情况下对相同大小执行第二次调用)以确保您收到以下消息。

我还强烈建议检查 select() 中的 return 以及更新的集合(因为在这种情况下 select() 可以 return 在没有可读套接字的情况下,例如,如果捕获到信号)。 我还注意到,在您当前的使用中,select() 并没有给您带来太多的阻碍 recvmsg() 调用。