基于libevent库实现http-sever-restful-API

一、环境搭建:

在这里插入图片描述

参考:https://blog.csdn.net/Zhouzi_heng/article/details/122913494

下载libevent:https://libevent.org/

1.编译libevent-2.1.11-stable

交叉编译:

mkdir compile_result
./configure --prefix=/home/test/libevent/libevent-2.1.11-stable/compile_result --host=mipsel-openwrt-linux CC=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-gcc CXX=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-musl-g++
export STAGING_DIR=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin:$STAGING_DIR
make && make install

在ubuntu 环境

mkdir compile_result_ubuntu
./configure --prefix=/home/test/libevent/libevent-2.1.11-stable/compile_result_ubuntu
make && make install

2.cJSON库

下载cJSON库:

https://github.com/DaveGamble/cJSON

在这里插入图片描述

使用方法:cJSON

lib_make.sh

#!/bin/sh
chmod 0777 ./*
cd /home/test/libevent/libevent-2.1.11-stable
tar -cvf compile_result_ubuntu.tar compile_result_ubuntu
cd -
cp /home/test/libevent/libevent-2.1.11-stable/compile_result_ubuntu.tar .        
tar -xvf compile_result_ubuntu.tar
gcc -shared -fPIC cJSON.c -o libcjson.so #cJSON动态库
cp ./mylist.h ./compile_result_ubuntu/include
cp ./cJSON.h ./compile_result_ubuntu/include
cp ./libcjson.so ./compile_result_ubuntu/lib
cp ./compile_result_ubuntu/lib/libevent_pthreads-2.1.so.7.0.0 ./compile_result_ubuntu/lib/libevent_pthreads.so
cp ./compile_result_ubuntu/lib/libevent_core-2.1.so.7.0.0    ./compile_result_ubuntu/lib/libevent_core.so
cp ./compile_result_ubuntu/lib/libevent-2.1.so.7.0.0 ./compile_result_ubuntu/lib/libevent.so
chmod 0777 ./*

二、makefile

CC = gcc
CFLAGS = -I./compile_result_ubuntu/include -L./compile_result_ubuntu/lib -levent -lcjson -lm
TARGET = main_ubuntu_http

all:
	$(CC) -o $(TARGET) http_server.c $(CFLAGS)

.PHONY:clean
clean:
	rm -rf *.o $(TARGET)

三、code

#include <stdio.h>
#include <stdlib.h>
#include <evhttp.h>
#include <event.h>
#include <string.h>
#include "mylist.h"
#include "cJSON.h"
#include "event2/http.h"
#include "event2/event.h"
#include "event2/buffer.h"
#include "event2/bufferevent.h"
#include "event2/bufferevent_compat.h"
#include "event2/http_struct.h"
#include "event2/http_compat.h"
#include "event2/util.h"
#include "event2/listener.h"
#define BUF_MAX 1024*16
#define MAX_NAME_SIZE 20
#define MAX_PHONE_NUM_SIZE 20
#define MAX_EMAIL_SIZE 40

// 员工信息主要有,名字,年龄,电话,邮件
typedef struct
{
    int id;
    char name[MAX_NAME_SIZE];               //名字
    int age;                                //年龄
    char phone_number[MAX_PHONE_NUM_SIZE];  //电话号码
    char email[MAX_EMAIL_SIZE];             //邮件
}Staff_st;

//双向循环链表节点
typedef struct     
{
    Staff_st data;          //数据域
    struct list_head list;  //小结构体,存放的是大结构体的前驱指针和后继指针
}LinkNode;

LinkNode * head;        //员工信息链表头节点

//列出所有员工信息
void display_list()     
{
    LinkNode *ptr=NULL;
    LinkNode *n=NULL;
    static int flag = 1;
    if(flag){
        printf("姓名\t年龄\t电话号码\t邮箱\t\n");
        flag = 0;
    }

    list_for_each_entry_safe(ptr,n,&(head->list),list){
        printf("%s\t%d\t%s\t%s\t\n",ptr->data.name,ptr->data.age,ptr->data.phone_number,ptr->data.email);
    }
}

//添加员工信息
void staff_add(char *buf)   
{
    int age;
    char *name;
    char *email;
    char *phone_number;
    cJSON *root,*item;
    root = cJSON_Parse(buf);
    if (!root) {
        const char *err = cJSON_GetErrorPtr();
        printf("Error before: [%s]", err);
        free((void *)err);
        return;
    }

    item = cJSON_GetObjectItem(root,"name");
    if(item != NULL){
        //判断是不是字符串
        if(item->type == cJSON_String){
            //获取字符串中的值
            name = item->valuestring;          
        }
    }
    item = cJSON_GetObjectItem(root,"age");
    if(item != NULL){
        //判断是不是字符串
        if(item->type == cJSON_Number){
            //获取字符串中的值
            age = item->valueint;          
        }
    }
    item = cJSON_GetObjectItem(root,"phone_number");
    if(item != NULL){
        //判断是不是字符串
        if(item->type == cJSON_String){
            //获取字符串中的值
            phone_number = item->valuestring;          
        }
    }
    item = cJSON_GetObjectItem(root,"email");
    if(item != NULL){
        //判断是不是字符串
        if(item->type == cJSON_String){
            //获取字符串中的值
            email = item->valuestring;          
        }
    }
    Staff_st data;
    data.age = age;
    strcpy(data.name,name);
    strcpy(data.phone_number,phone_number);
    strcpy(data.email,email);
    LinkNode * new = (LinkNode *)malloc(sizeof(LinkNode));
    if(new!=NULL){
        new->data = data;
        new->list.next = NULL;
        new->list.prev = NULL;
    }
    if(list_empty(&(new->list))){
        return;
    }
    list_add_tail(&(new->list),&(head->list));

    display_list();
}

//解析post请求数据
void get_post_message(char *buf, struct evhttp_request *req)
{
    size_t post_size = 0;

    post_size = evbuffer_get_length(req->input_buffer);//获取数据长度
    printf("====line:%d,post len:%u\n",__LINE__,post_size);
    if (post_size <= 0){
        printf("====line:%d,post msg is empty!\n",__LINE__);
        return;
    }
    else{
        size_t copy_len = post_size > BUF_MAX ? BUF_MAX : post_size;
        printf("====line:%d,post len:%d, copy_len:%u\n",__LINE__,post_size,copy_len);
        memcpy(buf, evbuffer_pullup(req->input_buffer,-1), copy_len);
        buf[post_size] = '\0';
        printf("====line:%d,post msg:%s\n",__LINE__,buf);
    }
}

char *staff_get_info_by_name(char *name)  
{
    if(name == NULL)
        return NULL;
    cJSON *root,*item;
    LinkNode *ptr=NULL;
    LinkNode *n=NULL;
    int i=1;
    char num[20];
    printf("====%d:send all staff name info\n",__LINE__);
    root = cJSON_CreateObject();    

    list_for_each_entry_safe(ptr,n,&(head->list),list){
        if(strcmp(ptr->data.name,name) == 0){
            item = cJSON_CreateObject();
            cJSON_AddItemToObject(item,"name",cJSON_CreateString(ptr->data.name));
            cJSON_AddItemToObject(item,"age",cJSON_CreateNumber(ptr->data.age));
            cJSON_AddItemToObject(item,"phone_number",cJSON_CreateString(ptr->data.phone_number));
            cJSON_AddItemToObject(item,"email",cJSON_CreateString(ptr->data.email));
            memset(num,0,sizeof(num));
            snprintf(num,sizeof(num),"%d",i++);
            cJSON_AddItemToObject(root,num,item);
        }
    }

    char *res = cJSON_Print(root);
    cJSON_Delete(root);
    return res;
}

//解析http头,主要用于get请求时解析uri和请求参数
char *find_http_header(struct evhttp_request *req,struct evkeyvalq *params,const char *query_char)
{
    printf("====line:%d ====func:%s\n",__LINE__,__FUNCTION__);
    if(req == NULL || params == NULL || query_char == NULL){
        printf("====line:%d,%s\n",__LINE__,"input params is null.");
        return NULL;
    }

    struct evhttp_uri *decoded = NULL;
    char *query = NULL; 
    char *query_result = NULL;
    const char *path;
    const char *uri = evhttp_request_get_uri(req);//获取请求uri

    if(uri == NULL){
        printf("====line:%d,evhttp_request_get_uri return null\n",__LINE__);
        return NULL;
    }
    else{
        printf("====line:%d,Got a GET request for <%s>\n",__LINE__,uri);
    }

    //解码uri
    decoded = evhttp_uri_parse(uri);
    if (!decoded) {
        printf("====line:%d,It's not a good URI. Sending BADREQUEST\n",__LINE__);
        evhttp_send_error(req, HTTP_BADREQUEST, 0);
        return;
    }

    //获取uri中的path部分
    path = evhttp_uri_get_path(decoded);
    if (path == NULL) {
        path = "/";
    }
    else{
        printf("====line:%d,path is:%s\n",__LINE__,path);
    }

    //获取uri中的参数部分
    query = (char*)evhttp_uri_get_query(decoded);
    if(query == NULL){
        printf("====line:%d,evhttp_uri_get_query return null\n",__LINE__);
        return NULL;
    }
    else{
        printf("====line:%d,query is:%s\n",__LINE__,query);
    }

    //查询指定参数的值
    evhttp_parse_query_str(query, params);          
    query_result = (char*)evhttp_find_header(params, query_char);

    return query_result;
}

//处理testget资源   get请求
void http_handler_testget_msg(struct evhttp_request *req,void *arg)
{
    if(req == NULL){
        printf("====line:%d,%s\n",__LINE__,"input param req is null.");
        return;
    }

    char *name = NULL;
    char *data = NULL;
    struct evkeyvalq sign_params = {0};
    // struct evhttp_uri
    name = find_http_header(req,&sign_params,"name");//获取get请求uri中的sign参数
    if(name == NULL){
        printf("====line:%d,%s\n",__LINE__,"request uri no param name.");
        return;
    }
    //回响应
    struct evbuffer *retbuff = NULL;
    retbuff = evbuffer_new();
    if(retbuff == NULL){
        printf("====line:%d,%s\n",__LINE__,"retbuff is null.");
        return;
    }
    printf("====line:%d,get request param: sign=[%s]\n",__LINE__,name);
    
    char *buf = staff_get_info_by_name(name);       //通过query方式找到name键值对对应的值
    if(buf == NULL){
        goto evbuffer_free_;
    }
    
    // data = find_http_header(req,&sign_params,"data");//获取get请求uri中的data参数
    // if(data == NULL){
    //     printf("====line:%d,%s\n",__LINE__,"request uri no param data.");
    // }
    // else{
    //     printf("====line:%d,get request param: data=[%s]\n",__LINE__,data);
    // }

    printf("\n");
    evbuffer_add_printf(retbuff,"%s\n",buf);
    evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
    evbuffer_free(retbuff);
    free(buf);
    return;

evbuffer_free_:
    evbuffer_add_printf(retbuff,"Receive get request,Thanks for the request!\n");
    evhttp_send_reply(req,HTTP_NOTFOUND,"Client",retbuff);
    evbuffer_free(retbuff);
}
char *staff_get_all()
{
    cJSON *root,*item;
    LinkNode *ptr=NULL;
    LinkNode *n=NULL;
    int i=1;
    char num[20];
    printf("send all staff info\n");
    root = cJSON_CreateObject();    
    list_for_each_entry_safe(ptr,n,&(head->list),list){
        item = cJSON_CreateObject();
        cJSON_AddItemToObject(item,"name",cJSON_CreateString(ptr->data.name));
        cJSON_AddItemToObject(item,"age",cJSON_CreateNumber(ptr->data.age));
        cJSON_AddItemToObject(item,"phone_number",cJSON_CreateString(ptr->data.phone_number));
        cJSON_AddItemToObject(item,"email",cJSON_CreateString(ptr->data.email));
        memset(num,0,sizeof(num));
        snprintf(num,sizeof(num),"%d",i++);
        cJSON_AddItemToObject(root,num,item);
    }
    char *res = cJSON_Print(root);
    cJSON_Delete(root);
    return res;
}

//处理/test post get请求
void http_handler_test_msg(struct evhttp_request *req,void *arg)
{
    printf("====line:%d ====func:%s\n",__LINE__,__FUNCTION__);
    if(req == NULL){
        printf("====line:%d,%s\n",__LINE__,"input param req is null.");
        return;
    }
    if(req->type == EVHTTP_REQ_PUT){       //修改
        return;
    }
    printf("====line:%d ====func:%s\n",__LINE__,__FUNCTION__);
    char buf[BUF_MAX] = {0};
    get_post_message(buf, req);//获取请求数据,一般是json格式的数据
    if(buf == NULL){
        printf("====line:%d,%s\n",__LINE__,"get_post_message return null.");
        return;
    }
    //回响应
    struct evbuffer *retbuff = NULL;
    retbuff = evbuffer_new();
    if(retbuff == NULL)
    {
        printf("====line:%d,%s\n",__LINE__,"retbuff is null.");
        return;
    }

    if(req->type == EVHTTP_REQ_POST){               //员工信息增加  处理get请求
        //使用json库解析数据   将数据增加到链表中
        staff_add(buf);
        printf("====line:%d,request data:%s\n",__LINE__,buf);
    }
    if(req->type == EVHTTP_REQ_GET){                //获取所有员工信息  处理post请求
        char *staff_buf = staff_get_all();
        evbuffer_add_printf(retbuff,"%s\n",staff_buf);
        evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
        free(staff_buf);
        goto buff_free_;
    }
    evbuffer_add_printf(retbuff,"Receive post request,Thanks for the request!\n");
    evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
buff_free_:
    evbuffer_free(retbuff);
}

//通过员工名字查找
int staff_change_by_name(char *json_buf)        
{
    printf("====line:%d ====func:%s\n",__LINE__,__FUNCTION__);
    int age = -1;
    char *name = NULL;
    char *email = NULL;
    char *phone_number = NULL;
    cJSON *item;
    cJSON *root = cJSON_Parse(json_buf);
    if(!root){
        const char *err = cJSON_GetErrorPtr();
        printf("Error before: [%s]\n", err);
        free((void *)err);
        return NULL;
    }

    item = cJSON_GetObjectItem(root,"name");    //get name
    if(item != NULL){
        if(item->type == cJSON_String){
            //获取字符串中的值
            name = item->valuestring;          
        }
    }

    item = cJSON_GetObjectItem(root,"age");     //get age
    if(item != NULL){
        if(item->type == cJSON_Number){
            age = item->valueint;
        }
    }
    item = cJSON_GetObjectItem(root,"phone_number");    //get phone_number
    if(item != NULL){
        if(item->type == cJSON_String){
            phone_number = item->valuestring;          
        }
    }
    item = cJSON_GetObjectItem(root,"email");    //get email
    if(item != NULL){
        if(item->type == cJSON_String){
            email = item->valuestring;          
        }
    }

    LinkNode *ptr=NULL;
    LinkNode *n=NULL;

    list_for_each_entry_safe(ptr,n,&(head->list),list){ //change linklist
        if(strcmp(ptr->data.name,name) == 0){
            if(age != -1){
                ptr->data.age = age;
            }
            if(phone_number != NULL){
                strncpy(ptr->data.phone_number,phone_number,MAX_PHONE_NUM_SIZE);
            }
            if(email != NULL){
                strncpy(ptr->data.email,email,MAX_EMAIL_SIZE);
            }
            cJSON_Delete(root);
            return 0;
        }
    }

    cJSON_Delete(root);
    return -1;    
}

//获取所有员工信息
char *staff_get_all_name()  
{
    cJSON *root,*item;
    LinkNode *ptr=NULL;
    LinkNode *n=NULL;
    int i=1;
    char num[20];
    printf("====%d:send all staff name info\n",__LINE__);
    root = cJSON_CreateObject();    

    list_for_each_entry_safe(ptr,n,&(head->list),list){
        item = cJSON_CreateObject();
        cJSON_AddItemToObject(item,"name",cJSON_CreateString(ptr->data.name));
        memset(num,0,sizeof(num));
        snprintf(num,sizeof(num),"%d",i++);
        cJSON_AddItemToObject(root,num,item);
    }

    char *res = cJSON_Print(root);
    cJSON_Delete(root);
    return res;
}

//处理/name资源  get put请求
void http_handler_test_token_msg(struct evhttp_request *req,void *arg)
{
    printf("====line:%d ====func:%s\n",__LINE__,__FUNCTION__);
    if(req == NULL){
        printf("====line:%d,%s\n",__LINE__,"input param req is null.");
        return;
    }

    char buf[BUF_MAX] = {0};
    get_post_message(buf, req);//获取请求数据,一般是json格式的数据
    if(buf == NULL){
        printf("====line:%d,%s\n",__LINE__,"get_post_message return null.");
        return;
    }
     //回响应
    struct evbuffer *retbuff = NULL;
    retbuff = evbuffer_new();
    if(retbuff == NULL){
        printf("====line:%d,%s\n",__LINE__,"retbuff is null.");
        return;
    }

    switch(req->type)
    {
        case EVHTTP_REQ_GET:       //查找
        {
            char *staff_buf = staff_get_all_name();
            evbuffer_add_printf(retbuff,"%s\n",staff_buf);
            evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
            free(staff_buf);
            goto buff_free_;
            break;
        }
        case EVHTTP_REQ_PUT:       //修改
        {
            if(staff_change_by_name(buf) == 0){
                evbuffer_add_printf(retbuff,"Change info successful,Thanks for the request!\n");
                evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
            }
            else{
                evbuffer_add_printf(retbuff,"Change info failed!\nThanks for the request!\n");
                evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
            }
            goto buff_free_;
            break;
        }
        default:
            break;
    }

    evbuffer_add_printf(retbuff,"Receive post request,Thanks for the request!\n");
    evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
buff_free_:
    evbuffer_free(retbuff);
}


// gcc http_server.c -levent -lcjson -lm
int main()
{
    struct evhttp *http_server = NULL;
    short http_port = 8081;
    char *http_addr = "0.0.0.0";

    //初始化员工链表
    head = (LinkNode *)malloc(sizeof(LinkNode));
    if(head!=NULL){
        INIT_LIST_HEAD(&(head->list));
    }

    //初始化
    event_init();
    //启动http服务端
    http_server = evhttp_start(http_addr,http_port);
    if(http_server == NULL){
        printf("====line:%d,%s\n",__LINE__,"http server start failed.");
        return -1;
    }

    //设置请求超时时间(s)
    evhttp_set_timeout(http_server,5);
    //设置事件处理函数,evhttp_set_cb针对每一个事件(请求)注册一个处理函数,
    //区别于evhttp_set_gencb函数,是对所有请求设置一个统一的处理函数

    evhttp_set_cb(http_server,"/test",http_handler_test_msg,NULL);
    evhttp_set_cb(http_server,"/test/name",http_handler_test_token_msg,NULL);
    evhttp_set_cb(http_server,"/testget",http_handler_testget_msg,NULL);

    //循环监听
    event_dispatch();
    //实际上不会释放,代码不会运行到这一步
    evhttp_free(http_server);

    return 0;
}

mylist.h

#ifndef __DLIST_H
#define __DLIST_H

/* This file is from Linux Kernel (include/linux/list.h)
* and modified by simply removing hardware prefetching of list items.
* Here by copyright, credits attributed to wherever they belong.
* Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
*/

/*
* Simple doubly linked list implementation.
*
* Some of the internal functions (“__xxx”) are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
/**
 * container_of - cast a member of a structure out to the containing structure
 *
 * @ptr:	the pointer to the member.
 * @type:	the type of the container struct this is embedded in.
 * @member:	the name of the member within the struct.
 *
 */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({			\
        const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
        (type *)( (char *)__mptr - offsetof(type,member) );}
/*
 * These are non-NULL pointers that will result in page faults
 * under normal circumstances, used to verify that nobody uses
 * non-initialized list entries.
 */
#define LIST_POISON1  ((void *) 0x00100100)
#define LIST_POISON2  ((void *) 0x00200)

//指针域部分,小结构体,用它来构建“纯粹链表”
struct list_head {
	struct list_head *next, *prev;
};

//节点结构体变量初始化
#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)

//节点结构体指针初始化
#define INIT_LIST_HEAD(ptr) do { \
	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/

//将new节点插入到prev和next节点之间
static inline void __list_add(struct list_head *new,
				struct list_head *prev,
				struct list_head *next)
{
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}

/**
* list_add – add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
//将new节点插入到head节点后面
static inline void list_add(struct list_head *new, struct list_head *head)
{
	__list_add(new, head, head->next);
}

/**
* list_add_tail – add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
//将new节点插入到head的前面
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
	__list_add(new, head->prev, head);
}

/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
//取出prev和next节点之间的结点
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
	next->prev = prev;
	prev->next = next;
}

/**
* list_del – deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
*/
//取出entry结点:让entry独立出来,前后指针域指向0地址
static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	entry->next = (void *) 0;
	entry->prev = (void *) 0;
}

/**
* list_del_init – deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
//取出entry结点:让entry独立出来,前后指针域指向自己的地址
static inline void list_del_init(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	INIT_LIST_HEAD(entry);
}

/**
* list_move – delete from one list and add as another’s head
* @list: the entry to move
* @head: the head that will precede our entry
*/
//将list移动到head后面
static inline void list_move(struct list_head *list,
				struct list_head *head)
{
	__list_del(list->prev, list->next);
	list_add(list, head);
}

/**
* list_move_tail – delete from one list and add as another’s tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
//将list移动到head前面
static inline void list_move_tail(struct list_head *list,
					struct list_head *head)
{
	__list_del(list->prev, list->next);
	list_add_tail(list, head);
}

/**
* list_empty – tests whether a list is empty
* @head: the list to test.
*/
//空链表判断
static inline int list_empty(struct list_head *head)
{
	return head->next == head;
}

//将list链表与head链表进行拼接
//拼接完的链表头是head
//比如:list: 1 2 3 4 5 6 7
//      head: 11 22 33 44
//      结果:head : 1 2 3 4 5 6 7 11 22 33 44
static inline void __list_splice(struct list_head *list,
					struct list_head *head)
{
	struct list_head *first = list->next;
	struct list_head *last = list->prev;
	struct list_head *at = head->next;

	first->prev = head;
	head->next = first;

	last->next = at;
	at->prev = last;
}

/**
* list_splice – join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}

/**
* list_splice_init – join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}

/**
* list_entry – get the struct for this entry
* @ptr:    the &struct list_head pointer.
* @type:    the type of the struct this is embedded in.
* @member:    the name of the list_struct within the struct.
*/
//小结构体指针ptr,大结构体类型type,小结构体在大结构体内部的成员名
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
//小结构体的地址 - 偏移量 = 大结构体的地址

/**
* list_for_each    -    iterate over a list
* @pos:    the &struct list_head to use as a loop counter.
* @head:    the head for your list.
*/

//遍历链表的for循环,每一次循环体内得到的就是一个小结构体指针
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)

/**
* list_for_each_prev    -    iterate over a list backwards
* @pos:    the &struct list_head to use as a loop counter.
* @head:    the head for your list.
*/
//从后往前遍历
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); \
pos = pos->prev)

/**
* list_for_each_safe    -    iterate over a list safe against removal of list entry
* @pos:    the &struct list_head to use as a loop counter.
* @n:        another &struct list_head to use as temporary storage
* @head:    the head for your list.
*/
//安全的遍历,防止在循环体中有对节点的删除操作,这样会导致下一次进入循环体出现段错误
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)

/**
* list_for_each_entry    -    iterate over list of given type
* @pos:    the type * to use as a loop counter.
* @head:    the head for your list.
* @member:    the name of the list_struct within the struct.
*/
//遍历过程中,得到大结构体指针:
//pos是遍历过程中的大结构体指针变量,
//head是小结构体链表头指针
//member小结构体在大结构体里面的成员名
#define list_for_each_entry(pos, head, member)                \
for (pos = list_entry((head)->next, typeof(*pos), member);    \
&pos->member != (head);                     \
pos = list_entry(pos->member.next, typeof(*pos), member))

/**
* list_for_each_entry_safe – iterate over list of given type safe against removal of list entry
* @pos:    the type * to use as a loop counter.
* @n:        another type * to use as temporary storage
* @head:    the head for your list.
* @member:    the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member)            \
for (pos = list_entry((head)->next, typeof(*pos), member),    \
n = list_entry(pos->member.next, typeof(*pos), member);    \
&pos->member != (head);                     \
pos = n, n = list_entry(n->member.next, typeof(*n), member))

#endif

四、测试

myt.sh

myeth=ens33						#选择网卡
string=`ifconfig $my_eth`		#ifconfig ens33
string=${string#*inet addr:}	#从左向右 截取第一个匹配到 inet addr: 	后面的值
string=${string%%  Bcast*}		#从右向左 截取最后一个匹配到   Bcast 	后面的值
echo $string					#获取本机ip
# string=192.168.5.241
port=8081						#端口号

if [ $1 = "make" ]
then
	#export STAGING_DIR=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin:$STAGING_DIR
	# STAGING_DIR=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin
	echo $(make)
	# set -x 
	# echo `./main_http_ubuntu`
elif [ $1 = "post" ]
then
    curl -X POST -H "Content-Type: application/json" --url "http://${string}:${port}/test" -d '{"name" :"xxx", "age" : 18,"phone_number" :"123","email" :"yyh@123.com"}'
    curl -X POST -H "Content-Type: application/json" --url "http://${string}:${port}/test" -d '{"name" :"xxx1", "age" : 19,"phone_number" :"1231","email" :"yyh@1231.com"}'
    curl -X POST -H "Content-Type: application/json" --url "http://${string}:${port}/test" -d '{"name" :"xxxj", "age" : 20,"phone_number" :"1232","email" :"yyh@1232.com"}'             
elif [ $1 = "get" ]
then
	curl -X GET -H "Content-Type: application/json" --url "http://${string}:${port}/test" -g
elif [ $1 = "getname" ]
then
	curl -X GET -H "Content-Type: application/json" --url "http://${string}:${port}/test/name" -g
elif [ $1 = "put" ]
then
	curl -X PUT -H "Content-Type: application/json" --url "http://${string}:${port}/test/name" -d '{"name" :"xxx", "age" : 2022,"phone_number" :"123222","email" :"yyhj@1232.com"}' 
elif [ $1 = "query_get" ]	#通过query方式获取值
then
	curl -X GET -H "Content-Type: application/json" --url "http://192.168.183.128:8081/testget?name=xxx" -g
fi

测试结果如下:

运行http server

./main_http_ubuntu

在这里插入图片描述

./myt.sh getname

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yengi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值