linux 使用PF_NETLINK协议用户进程间通信, 服务端收不到请求是什么问题? 正确的服务端客户端代码应该怎么写
时间: 2023-11-28 16:48:26 浏览: 86
linux下用户程序同内核通信详解(netlink机制)
如果服务端收不到请求,可能有以下几个问题:
1. 服务端没有正确地绑定监听的 netlink socket,需要使用 `bind()` 函数将其绑定到正确的 netlink family 和 multicast group 上;
2. 服务端没有正确地设置 netlink socket 的接收缓冲区大小,可以使用 `setsockopt()` 函数来设置;
3. 客户端没有正确地发送请求,需要使用 `sendto()` 函数发送请求,并且请求结构体的长度需要和发送的字节数相等。
下面是一个简单的服务端和客户端代码示例:
服务端:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#define NETLINK_USER 31
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
int main() {
// 创建 netlink socket
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if (sock_fd < 0) {
printf("Error creating socket.\n");
return -1;
}
// 绑定 netlink socket
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
src_addr.nl_groups = 0;
if (bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr)) < 0) {
printf("Error binding socket.\n");
return -1;
}
// 设置 netlink socket 接收缓冲区大小
int rcvbuf_size = 1024 * 1024;
setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf_size, sizeof(rcvbuf_size));
// 接收客户端请求
while (1) {
// 准备接收缓冲区
char recv_buf[1024];
memset(recv_buf, 0, sizeof(recv_buf));
iov.iov_base = recv_buf;
iov.iov_len = sizeof(recv_buf);
// 接收请求
memset(&dest_addr, 0, sizeof(dest_addr));
nlh = (struct nlmsghdr*)recv_buf;
nlh->nlmsg_len = NLMSG_SPACE(sizeof(int));
nlh->nlmsg_pid = 0;
nlh->nlmsg_flags = 0;
iov.iov_len = nlh->nlmsg_len;
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_name = &dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
recvmsg(sock_fd, &msg, 0);
// 解析请求数据
int* data = (int*)NLMSG_DATA(nlh);
printf("Received request: %d\n", *data);
// 构造响应数据
char resp_buf[1024];
memset(resp_buf, 0, sizeof(resp_buf));
nlh = (struct nlmsghdr*)resp_buf;
nlh->nlmsg_len = NLMSG_SPACE(sizeof(int));
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
data = (int*)NLMSG_DATA(nlh);
*data = *data * 2;
// 发送响应
iov.iov_base = (void*)NLMSG_DATA(nlh);
iov.iov_len = sizeof(int);
iov.iov_len = nlh->nlmsg_len;
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
msg.msg_name = &dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(sock_fd, &msg, 0);
}
return 0;
}
```
客户端:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#define NETLINK_USER 31
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
int main() {
// 创建 netlink socket
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if (sock_fd < 0) {
printf("Error creating socket.\n");
return -1;
}
// 准备请求数据
int data = 10;
char req_buf[1024];
memset(req_buf, 0, sizeof(req_buf));
nlh = (struct nlmsghdr*)req_buf;
nlh->nlmsg_len = NLMSG_SPACE(sizeof(int));
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
struct iovec iov_req;
iov_req.iov_base = &data;
iov_req.iov_len = sizeof(data);
iov.iov_len = nlh->nlmsg_len;
NLMSG_DATA(nlh) = &data;
// 发送请求
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_name = &dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov_req;
msg.msg_iovlen = 1;
sendmsg(sock_fd, &msg, 0);
// 接收响应
char resp_buf[1024];
memset(resp_buf, 0, sizeof(resp_buf));
iov.iov_base = resp_buf;
iov.iov_len = sizeof(resp_buf);
nlh = (struct nlmsghdr*)resp_buf;
memset(&dest_addr, 0, sizeof(dest_addr));
memset(&msg, 0, sizeof(msg));
msg.msg_name = &dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
recvmsg(sock_fd, &msg, 0);
// 解析响应数据
int* resp_data = (int*)NLMSG_DATA(nlh);
printf("Received response: %d\n", *resp_data);
return 0;
}
```
阅读全文