一、环境搭建:
参考: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