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()
调用。
我正在编写 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
.
但是当我尝试发送多个请求并在另一个线程中使用 sockfd
执行 select
时,然后 recvmsg
继续接收相同的消息并且永不停止。
是否需要设置任何标志以响应停止连续循环或任何其他方式?
recvmsg()
,当使用 MSG_PEEK
标志调用时,returns 数据但不会从套接字的接收队列中删除它,导致下一个接收 return再次读取相同的数据。
删除标志(或在没有它的情况下对相同大小执行第二次调用)以确保您收到以下消息。
我还强烈建议检查 select()
中的 return 以及更新的集合(因为在这种情况下 select()
可以 return 在没有可读套接字的情况下,例如,如果捕获到信号)。
我还注意到,在您当前的使用中,select()
并没有给您带来太多的阻碍 recvmsg()
调用。