C0reFast记事本

to inspire confidence in somebody.

0%

一个简单的内核Socket Client例子

一个简单的内核Socket Client例子,实现一个简单的客户端,发送一些数据到服务端,并从服务端接受数据打印到dmesg。在Linux 4.8.13内核测试通过。

client_example.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include<linux/in.h>
#include<linux/inet.h>
#include<linux/socket.h>
#include<net/sock.h>
#include<linux/init.h>
#include<linux/module.h>

#define BUFFER_SIZE 1024

int connect_send_recv(void){
struct socket *sock;
struct sockaddr_in s_addr;
unsigned short port_num = 8888;
int ret = 0;
char *send_buf = NULL;
char *recv_buf = NULL;
struct kvec send_vec, recv_vec;
struct msghdr send_msg, recv_msg;

/* kmalloc a send buffer*/
send_buf = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if (send_buf == NULL) {
printk("client: send_buf kmalloc error!\n");
return -1;
}

/* kmalloc a receive buffer*/
recv_buf = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if(recv_buf == NULL){
printk("client: recv_buf kmalloc error!\n");
return -1;
}

memset(&s_addr, 0, sizeof(s_addr));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(port_num);

s_addr.sin_addr.s_addr = in_aton("192.168.1.10");
sock = (struct socket *)kmalloc(sizeof(struct socket), GFP_KERNEL);

// 创建一个sock, &init_net是默认网络命名空间
ret = sock_create_kern(&init_net, AF_INET, SOCK_STREAM, 0, &sock);
if (ret < 0) {
printk("client:socket create error!\n");
return ret;
}
printk("client: socket create ok!\n");

//连接
ret = sock->ops->connect(sock, (struct sockaddr *)&s_addr, sizeof(s_addr), 0);
if (ret != 0) {
printk("client: connect error!\n");
return ret;
}
printk("client: connect ok!\n");

memset(send_buf, 'a', BUFFER_SIZE);

memset(&send_msg, 0, sizeof(send_msg));
memset(&send_vec, 0, sizeof(send_vec));

send_vec.iov_base = send_buf;
send_vec.iov_len = BUFFER_SIZE;

// 发送数据
ret = kernel_sendmsg(sock, &send_msg, &send_vec, 1, BUFFER_SIZE);
if (ret < 0) {
printk("client: kernel_sendmsg error!\n");
return ret;
} else if(ret != BUFFER_SIZE){
printk("client: ret!=BUFFER_SIZE");
}
printk("client: send ok!\n");

memset(recv_buf, 0, BUFFER_SIZE);

memset(&recv_vec, 0, sizeof(recv_vec));
memset(&recv_msg, 0, sizeof(recv_msg));

recv_vec.iov_base = recv_buf;
recv_vec.iov_len = BUFFER_SIZE;

// 接收数据
ret = kernel_recvmsg(sock, &recv_msg, &recv_vec, 1, BUFFER_SIZE, 0);
printk("client: received message:\n %s\n", recv_buf);

// 关闭连接
kernel_sock_shutdown(sock, SHUT_RDWR);
sock_release(sock);

return 0;
}

static int client_example_init(void){
printk("client: init\n");
return connect_send_recv();
}

static void client_example_exit(void){
printk("client: exit!\n");
}

module_init(client_example_init);
module_exit(client_example_exit);
MODULE_LICENSE("GPL");

Makefile:

1
2
3
4
5
obj-m := client_example.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

在192.168.1.10上 nc -lk 8888 监听8888端口,作为服务端,等待数据后输入 111111111111111

客户端:

1
2
3
4
5
6
7
8
9
10
11
12
make
sudo insmod client_example.ko #加载模块
sudo rmmod client_example #卸载模块
sudo journalctl -k #查看dmesg

Jan 16 10:50:58 work kernel: client: init
Jan 16 10:50:58 work kernel: client: socket create ok!
Jan 16 10:50:58 work kernel: client: connect ok!
Jan 16 10:50:58 work kernel: client: send ok!
Jan 16 10:51:10 work kernel: client: received message:
111111111111111
Jan 16 10:51:22 sae kernel: client: exit!

服务端:

1
2
$ nc -lk 8888
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa111111111111111
Chen Fu wechat
新注册了公众号,同步更新,长按关注,可以第一时间收到推送