to inspire confidence in somebody.

0%

一个简单的内核Socket Client例子

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

client_example.c:

1
#include<linux/in.h>
2
#include<linux/inet.h>
3
#include<linux/socket.h>
4
#include<net/sock.h>
5
#include<linux/init.h>
6
#include<linux/module.h>
7
8
#define BUFFER_SIZE 1024
9
10
int connect_send_recv(void){
11
    struct socket *sock;
12
    struct sockaddr_in s_addr;
13
    unsigned short port_num = 8888;
14
    int ret = 0;
15
    char *send_buf = NULL;
16
    char *recv_buf = NULL;
17
    struct kvec send_vec, recv_vec;
18
    struct msghdr send_msg, recv_msg;
19
20
    /* kmalloc a send buffer*/
21
    send_buf = kmalloc(BUFFER_SIZE, GFP_KERNEL);
22
    if (send_buf == NULL) {
23
        printk("client: send_buf kmalloc error!\n");
24
        return -1;
25
    }
26
27
    /* kmalloc a receive buffer*/
28
    recv_buf = kmalloc(BUFFER_SIZE, GFP_KERNEL);
29
    if(recv_buf == NULL){
30
        printk("client: recv_buf kmalloc error!\n");
31
        return -1;
32
    }
33
34
    memset(&s_addr, 0, sizeof(s_addr));
35
    s_addr.sin_family = AF_INET;
36
    s_addr.sin_port = htons(port_num);
37
38
    s_addr.sin_addr.s_addr = in_aton("192.168.1.10");
39
    sock = (struct socket *)kmalloc(sizeof(struct socket), GFP_KERNEL);
40
41
    // 创建一个sock, &init_net是默认网络命名空间
42
    ret = sock_create_kern(&init_net, AF_INET, SOCK_STREAM, 0, &sock);
43
    if (ret < 0) {
44
        printk("client:socket create error!\n");
45
        return ret;
46
    }
47
    printk("client: socket create ok!\n");
48
49
    //连接
50
    ret = sock->ops->connect(sock, (struct sockaddr *)&s_addr, sizeof(s_addr), 0);
51
    if (ret != 0) {
52
        printk("client: connect error!\n");
53
        return ret;
54
    }
55
    printk("client: connect ok!\n");
56
57
    memset(send_buf, 'a', BUFFER_SIZE);
58
59
    memset(&send_msg, 0, sizeof(send_msg));
60
    memset(&send_vec, 0, sizeof(send_vec));
61
62
    send_vec.iov_base = send_buf;
63
    send_vec.iov_len = BUFFER_SIZE;
64
65
    // 发送数据
66
    ret = kernel_sendmsg(sock, &send_msg, &send_vec, 1, BUFFER_SIZE);
67
    if (ret < 0) {
68
        printk("client: kernel_sendmsg error!\n");
69
        return ret;
70
    } else if(ret != BUFFER_SIZE){
71
        printk("client: ret!=BUFFER_SIZE");
72
    }
73
    printk("client: send ok!\n");
74
75
    memset(recv_buf, 0, BUFFER_SIZE);
76
77
    memset(&recv_vec, 0, sizeof(recv_vec));
78
    memset(&recv_msg, 0, sizeof(recv_msg));
79
80
    recv_vec.iov_base = recv_buf;
81
    recv_vec.iov_len = BUFFER_SIZE;
82
83
    // 接收数据
84
    ret = kernel_recvmsg(sock, &recv_msg, &recv_vec, 1, BUFFER_SIZE, 0);
85
    printk("client: received message:\n %s\n", recv_buf);
86
87
    // 关闭连接
88
    kernel_sock_shutdown(sock, SHUT_RDWR);
89
    sock_release(sock);
90
91
    return 0;
92
}
93
94
static int client_example_init(void){
95
    printk("client: init\n");
96
    return connect_send_recv();
97
}
98
99
static void client_example_exit(void){
100
    printk("client: exit!\n");
101
}
102
103
module_init(client_example_init);
104
module_exit(client_example_exit);
105
MODULE_LICENSE("GPL");

Makefile:

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

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

客户端:

1
make
2
sudo insmod client_example.ko #加载模块
3
sudo rmmod client_example     #卸载模块
4
sudo journalctl -k            #查看dmesg
5
6
Jan 16 10:50:58 work kernel: client: init
7
Jan 16 10:50:58 work kernel: client: socket create ok!
8
Jan 16 10:50:58 work kernel: client: connect ok!
9
Jan 16 10:50:58 work kernel: client: send ok!
10
Jan 16 10:51:10 work kernel: client: received message:
11
                             111111111111111
12
                             Jan 16 10:51:22 sae kernel: client: exit!

服务端:

1
$ nc -lk 8888
2
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa111111111111111