linux如何创建PF_NETLINK协议通信,写出服务端和客户端
时间: 2023-11-27 15:54:53 浏览: 81
linux ftps服务端和客户端
5星 · 资源好评率100%
PF_NETLINK是Linux内核提供的一种用于内核与用户空间进程之间通信的协议。下面是一个简单的PF_NETLINK服务端和客户端的示例代码:
服务端代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#define NETLINK_TEST 25
#define MSG_LEN 100
int main(int argc, char *argv[]) {
int skfd;
struct sockaddr_nl saddr, daddr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
struct msghdr msg;
char msg_buf[MSG_LEN];
// 创建socket
skfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST);
if (skfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 绑定源地址
memset(&saddr, 0, sizeof(saddr));
saddr.nl_family = AF_NETLINK;
saddr.nl_pid = getpid();
saddr.nl_groups = 0;
if (bind(skfd, (struct sockaddr *)&saddr, sizeof(saddr)) != 0) {
perror("bind");
close(skfd);
exit(EXIT_FAILURE);
}
// 初始化目标地址
memset(&daddr, 0, sizeof(daddr));
daddr.nl_family = AF_NETLINK;
daddr.nl_pid = 0; // 目标地址为内核
daddr.nl_groups = 0;
// 构造netlink消息
nlh = (struct nlmsghdr *)msg_buf;
nlh->nlmsg_len = NLMSG_LENGTH(strlen("Hello from kernel!"));
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nlh), "Hello from kernel!");
// 设置iov
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
// 设置msghdr
memset(&msg, 0, sizeof(msg));
msg.msg_name = (void *)&daddr;
msg.msg_namelen = sizeof(daddr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
// 发送消息
if (sendmsg(skfd, &msg, 0) == -1) {
perror("sendmsg");
close(skfd);
exit(EXIT_FAILURE);
}
printf("Kernel message sent.\n");
close(skfd);
return 0;
}
```
客户端代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#define NETLINK_TEST 25
#define MSG_LEN 100
int main(int argc, char *argv[]) {
int skfd;
struct sockaddr_nl saddr, daddr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
struct msghdr msg;
char msg_buf[MSG_LEN];
// 创建socket
skfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST);
if (skfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 初始化源地址
memset(&saddr, 0, sizeof(saddr));
saddr.nl_family = AF_NETLINK;
saddr.nl_pid = getpid();
saddr.nl_groups = 0;
// 绑定源地址
if (bind(skfd, (struct sockaddr *)&saddr, sizeof(saddr)) != 0) {
perror("bind");
close(skfd);
exit(EXIT_FAILURE);
}
// 初始化目标地址
memset(&daddr, 0, sizeof(daddr));
daddr.nl_family = AF_NETLINK;
daddr.nl_pid = 0; // 目标地址为内核
daddr.nl_groups = 0;
// 构造netlink消息
nlh = (struct nlmsghdr *)msg_buf;
nlh->nlmsg_len = NLMSG_SPACE(MSG_LEN);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nlh), "Hello from user space!");
// 设置iov
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
// 设置msghdr
memset(&msg, 0, sizeof(msg));
msg.msg_name = (void *)&daddr;
msg.msg_namelen = sizeof(daddr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
// 发送消息
if (sendmsg(skfd, &msg, 0) == -1) {
perror("sendmsg");
close(skfd);
exit(EXIT_FAILURE);
}
printf("User message sent.\n");
// 接收消息
memset(&msg, 0, sizeof(msg));
msg.msg_name = (void *)&saddr;
msg.msg_namelen = sizeof(saddr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
if (recvmsg(skfd, &msg, 0) == -1) {
perror("recvmsg");
close(skfd);
exit(EXIT_FAILURE);
}
printf("Received message from kernel: %s\n", (char *)NLMSG_DATA(nlh));
close(skfd);
return 0;
}
```
运行上述服务端和客户端代码即可进行PF_NETLINK通信。注意需要以root权限运行程序。
阅读全文