recvmsg 在 NETLINK 套接字上进行选择

问题描述 投票:0回答:1

我正在编写 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
继续接收相同的消息并且永远不会停止。

我需要设置任何标志来响应停止连续循环或任何其他方式吗?

c netlink posix-select ipsec
1个回答
3
投票

recvmsg()
,当使用
MSG_PEEK
标志调用时,会返回数据,但不会将其从套接字的接收队列中删除,从而导致下一个接收再次返回相同的数据。

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

我还强烈建议检查

select()
的返回以及更新后的集合(因为在这种情况下,
select()
可以在没有可读套接字的情况下返回,例如,如果捕获到信号)。 我还想指出,在您当前的使用中,
select()
并没有为您提供比普通阻塞
recvmsg()
调用更多的功能。

© www.soinside.com 2019 - 2024. All rights reserved.