嵌入式在线商城

news2024/9/20 20:32:10

一、主线功能

1、设计与实现在线商城系统涉及到前端展示、后台管理以及数据库进行查找,功能包含登录页面、商品搜素、商品详细信息查找。

二、页面设计

2.1、商品搜索设计

2.2、商品详细信息展示设计

2.3、TCP并发服务器设计

HTTP是基于Tcp服务器搭建起来的

第一步,建立连接

//创建套接字并且监听 
int create_sever(const char *ip ,unsigned short port)
{	
    int option,optlen;
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (-1 == sockfd)
	{
		perror("fail socket");
		return -1;
    }
    optlen=sizeof(option);
    option=1;
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(void*)&option,optlen);
    struct sockaddr_in ser;
	ser.sin_family = AF_INET;
	ser.sin_port = htons(port);
	ser.sin_addr.s_addr = inet_addr(ip);
	int ret = bind(sockfd, (struct sockaddr *)&ser, sizeof(ser));
	if (-1 == ret)
	{
		perror("fail bind");
		return -1;
	}
	ret = listen(sockfd, 128);
	if (-1 == ret)
	{
		perror("fail listen");
		return -1;
	}
	
	return sockfd;
}

第二步、接收监听队列里面的套接字,并产生通信的套接字

  int connfd = accept(sockfd, NULL, NULL);
		if (-1 == connfd)
                {
                    perror("fail accept");
                    continnue;
}

 至此三次握手建立完毕

第三步、接收网页传过来的HTTP报文

//接收报文
int recv_http_request(int connfd,char *http_req,int maxlen)
{
    memset(http_req,0,maxlen);
    ssize_t size = recv(connfd,http_req,maxlen,0);
    if(size <= 0)
    {
        perror("fail1 recv");
        return size;
    }
    return size;
}
//将接收的内容进行解析,解析分为三步,方法、url、内容
int parse_http_request(char *http_req,HTTP_REQ_t *phttp)
{
    char buf[256] = {0};

    memset(phttp,0,sizeof(HTTP_REQ_t));
    char *p = strtok(http_req," ");
    if(NULL == p)
    {
        return -1;
    }
    strcpy(phttp->method,p);
    p = strtok(NULL," ");
    if(NULL == p)
    {
        return -1;
    }
    strcpy(phttp->url,p);
    p = strtok(NULL,"\0");
    if(NULL == p)
    {
        return -1;
    }
    p = strstr(p,"\r\n\r\n");
    if(NULL == p)
    {
        return -1;
    }
    strcpy(phttp->content,p+4);
    parse_phttp(phttp->content,buf);
    strcpy(phttp->content,buf);
    printf("--->%s\n",phttp->content);
    return 0;

}

第四步、对接收的报文需要的内容,进行发送

//先发送报文的头部
int send_http_head(int connfd)
{
    char *head ="HTTP/1.1 200 OK\r\n"
                "Content-Type: text/html; charset=utf-8\r\n"
                "Sever: my-web-sever\r\n"
                "Connection: keep-alive\r\n\r\n";
    ssize_t size = send(connfd,head,strlen(head),0);
    if(size < 0)
    {
        perror("fail send");
        return -1;
    }
    return 0;
}
//打开需要的文件的资源,并将该资源进行发送
int send_http_file(int connfd,char *filename)
{
    char buf[1024] = {0};
    int fd = open(filename,O_RDONLY);
    if(fd < 0)
    {
        perror("fail open file");
        return -1;
    }
    while(1)
    {
        ssize_t size = read(fd,buf,sizeof(buf));
        if(size <= 0)
        {
            break;
        }
        send(connfd,buf,size,0);
    }
    close(fd);
    return 0;
}
//发送响应请求
int send_http_reponse(int connfd,HTTP_REQ_t *phttp)
{
    char *p;
    int i = 0;
    char sfile[1024] = {0};
    send_http_head(connfd);
    char *q;
    p = strtok(phttp->url,"?");
    q = strtok(NULL,"\0");
    printf("%s",phttp->url);
    if(!strcmp(phttp->method,"GET"))//请求方法
    {
        if(!strcmp(phttp->url,"/"))
        {
            sprintf(sfile,"./res/denglu.html");
            send_http_file(connfd,sfile);
            return 0;
        }
        else if(strstr(phttp->url,".jpg") || strstr(phttp->url,".png"))
        {
            if(strstr(phttp->url,"200905"))
            {
                sprintf(sfile,".%s",phttp->url);
                send_http_file(connfd,sfile);
            }
            else
            {
                sprintf(sfile,"./res%s",phttp->url);
                send_http_file(connfd,sfile);
            }

            return 0;
        }
        else if(strstr(phttp->url,"/favicon.ico"))//图标
        {
            return 0;
        }
        else if(strstr(phttp->url,".html"))
        {
            if(strcmp(phttp->url,"/4.html")==0)//特殊的,四级页面,我们根据请求直接将网页的标签内容在此写好进行发送
            {
                sprintf(sfile,"./res%s",phttp->url);
                send_http_file(connfd,sfile);
                record = connfd;
                char *site = index(q,'='); 
                select_sqlite4(site+1);
                char buf[100] = "<body><html>";
                send(connfd,buf,strlen(buf),0);
            }
            else
            {
                sprintf(sfile,"./res%s",phttp->url);
                send_http_file(connfd,sfile);
            }
        }
    }
    else if(!strcmp(phttp->method,"POST"))
    {
        if(strstr(phttp->url,".html"))
        {
            if(strcmp(phttp->url,"/meaning.html") == 0)
            {
                sprintf(sfile,"./res%s",phttp->url);//与上述想法同理
                send_http_file(connfd,sfile);
                printf("sendfile = %s\n",sfile);
                record = connfd;
                select_sqlite(phttp->content);
                char buf[100] = "<body><html>";
                send(connfd,buf,strlen(buf),0);
                return 0;
            }
            sprintf(sfile,"./res%s",phttp->url);
            send_http_file(connfd,sfile);
            printf("sendfile = %s\n",sfile);
            return 0;
        }
    }
}

三、函数端口

接口

参数

返回值

接口描述

Intcallback(void*arg,intcolumn_cnt,char **column_value,char **column_name)

查到数据列数,地址集合,每一列列名的集合

0

回调函数

int select_sqlite(char *p)

数据库指针

fd

数据库查找

int create_sever(constchar*ip ,unsigned short port)

地址,端口

0

创造数据服务器端口号

int epoll_del_fd(int epfds,int fd)

文件描述符集合句柄,端口

0

删除文件描述符,从数组

int epoll_add_fd(int epfds,int fd,uint32_t event)

文件描述符集合句柄,端口

0

未来世界

intrecv_http_request(intconnfd,char *http_req,int maxlen)

文件描述符,结构体指针,最大长度

0

接受TCP报文请求

intparse_http_request(char*http_req,HTTP_REQ_t *phttp)

结构体对象指针,请求对象

0

对请求报文进行解析

int send_http_head(int connfd)

文件描述符

0

发送报文的头部

int send_http_file(int connfd,char *filename)

文件描述符,文件

0

发送报文想要的内容

intsend_http_reponse(intconnfd,HTTP_REQ_t *phttp)

文件描述符,结构体对象

0

发生报文进行服务器响应

四、并发服务器的设计

4.1、并发设计

主要用的是IO多路复用的epoll 进行设计,其资源消耗相对来说比较小,对于小型网页来说,完全够用,且效率高

4.2、设计过程

第一步、将创建好的套接字的文件描述添加到数组里面

第二步、遍历数组、查找当前的套接字

第三步、执行当前套接字所需运行的内容

//主函数 ,并发服务器
int main(int agrc,char *agrv[])
{
    int connfd = 0;
    char buf[1024] = {0};
    HTTP_REQ_t http;
    char http_req[4096] = {0};
    int ret = 0;
    int sockfd = create_sever("192.168.208.85",8080);
    if(sockfd == -1)
    {
        perror("fail socket");
        return -1;
    }
    int epfds = epoll_create(1024);
    if(-1 == epfds)
    {
        perror("fail epoll_create");
        return -1;
    }
    epoll_add_fd(epfds,sockfd,EPOLLIN);
    struct epoll_event evs[1024];
    while(1)
    {
        int cnt = epoll_wait(epfds,evs,1024,-1);
        if(cnt < 0)
        {
            perror("fail epoll_wait");
            return -1;
        }
        for(int i=0;i<cnt;i++)
        {
            if(sockfd == evs[i].data.fd)
            {
                int connfd = accept(sockfd, NULL, NULL);
		if (-1 == connfd)
                {
                    perror("fail accept");
                    continue;
                }
                epoll_add_fd(epfds, connfd, EPOLLIN);
            }
            else
            {
                memset(http_req,0,sizeof(http_req));
                recv_http_request(evs[i].data.fd,http_req,sizeof(http_req));
                printf("----------\n%s\n----------\n",http_req);
                ret = parse_http_request(http_req,&http);
                if(ret < 0)
                {
                    close(evs[i].data.fd);
                    continue;
                }
                printf("method : %s\n",http.method);
                printf("url    : %s\n",http.url);
                printf("content: %s\n",http.content);
                printf("----------------------------\n");
                int size = send_http_reponse(evs[i].data.fd,&http);
                if(size < 0)
                {
                    perror("fail2 recv");
                    epoll_del_fd(epfds,evs[i].data.fd);
                    close(evs[i].data.fd);
                    continue;
                }
                close(evs[i].data.fd);
            }
        }
    }
    return 0;
}


//增加此刻的文件描述符到数组中
int epoll_add_fd(int epfds,int fd,uint32_t event)
{
    struct epoll_event ev;
    ev.events = event;
    ev.data.fd = fd;
    int ret = epoll_ctl(epfds,EPOLL_CTL_ADD,fd,&ev);
    if(-1 == ret)
    {
        perror("fail epoll_ctl add");
        return -1;
    }
    return 0;
}
//删除数组中的文件描述符
int epoll_del_fd(int epfds,int fd)
{
    int ret = epoll_ctl(epfds, EPOLL_CTL_DEL, fd, NULL);
	if (ret < 0)
	{
		perror("fail epoll_ctl del");
		return -1;
	}
	return 0;
}

五、网页效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2103754.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Hadoop|HDFS篇】HDFS的Shell操作

1. 基本语法 hadoop fs 具体命令或者hadoop dfs 具体命令。 两个是完全相同的。 2. 命令大全 hadoop fs&#xff1a; Usage: hadoop fs [generic options][-appendToFile <localsrc> ... <dst>][-cat [-ignoreCrc] <src> ...][-checksum <src> ..…

Robotics: computational motion planning 部分笔记—— week 1 graph-based

grassfire algorithm 四周扩散性&#xff1b;从终点开始按照相邻最小距离格子移动 Dijkstra’s Algorithm 标明从起点开始的所有点的最短距离&#xff08;从上一节点继承&#xff09;&#xff0c;直到终点 A* Algorithm 带有启发性的&#xff0c;给出距离估计&#xff0c…

大数据-117 - Flink DataStream Sink 案例:写出到MySQL、写出到Kafka

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

LLM常见问题(RAG部分)

1. 什么是 Graph RAG&#xff1f; Graph RAG 是由悦数图数据提出的概念&#xff0c;是一种基于知识图谱的检索增强技术&#xff0c;通过构建图模型的知识表达&#xff0c;将实体和关系之间的联系用图的形式进行展示&#xff0c;然后利用大语言模型 LLM进行检索增强。 通过图技…

鸿蒙Harmony--状态变量更改通知--@Watch装饰器详解

风雨飘摇中&#xff0c;我心起伏&#xff0c; 万丈雄心&#xff0c;却难以施展。 天高地远&#xff0c;路途迷茫&#xff0c; 理想如星&#xff0c;却遥不可及。 千百次跌倒&#xff0c;千百次爬起&#xff0c; 在命运的手掌中&#xff0c;挣扎前行。 谁知我心中的热血滚烫&…

什么是科学碳目标(SBTI认证)

科学碳目标&#xff08;SBTI认证&#xff09;&#xff0c;这一绿色发展的璀璨明珠&#xff0c;是企业迈向可持续未来的重要里程碑。它不仅是全球环境信息研究中心(CDP)、联合国全球契约组织(UNGC)、世界资源研究所(WRI)与世界自然基金会(WWF)共同铸就的智慧结晶&#xff0c;更是…

【C++模板初阶】

文章目录 一、泛型编程二、函数模板1.函数模板概念2.函数模板格式3.函数模板的原理4 函数模板的实例化1. 隐式实例化2. 显式实例化不同类型形参传参时的处理 5.模板参数的匹配原则 三、类模板1 类模板的定义格式2 类模板的实例化 一、泛型编程 首先大家先思考一个问题&#xff…

Django form.save 方法的详细分析

在 Django 中&#xff0c;form.save() 方法是用于将表单中的数据保存到数据库的核心方法。它的功能和实现可以分为几个重要的部分&#xff0c;下面就是我对 form.save() 方法的详细分析&#xff1a; 1、问题背景 在 Django 中&#xff0c;我们经常会使用 Form 来处理用户提交的…

yum无法使用解决Could not resolve host: mirrorlist.centos.org; Unknown error

报错如下 2、问题原因 CentOS 7 的官方仓库在 2024 年 6 月 30 日之后已经停止维护。CentOS 7 的官方支持已经结束&#xff0c;部分仓库已被移至归档库。导致yum 命令无法找到所需的元数据文件。 3、解决方法 进入/etc/yum.repos.d目录下找到 CentOS-Base.repo cd /etc/yum.…

【鸿蒙蓝牙连接】

鸿蒙蓝牙连接 ble.startBLEScan startBLEScan(filters: Array, options?: ScanOptions): void 发起BLE扫描流程。 需要权限&#xff1a;ohos.permission.ACCESS_BLUETOOTH import { BusinessError } from ohos.base; function onReceiveEvent(data: Array<ble.ScanResu…

【iOS】暑期学习总结

暑期学习总结 前言无限轮播图换头像简单的网络请求UISearchController 前言 暑假在学校完成了五个项目&#xff0c;总的来说学习到了很多新的知识&#xff0c;这里对暑假中学习的内容进行一个小的总结&#xff0c;整理一些个人认为比较重点的内容。 无限轮播图 无限轮播图的…

PDF转换成Excel哪家强?热门工具大比拼

现在咱们周围电脑和手机一大堆&#xff0c;PDF和Excel这两种文件格式特别流行&#xff0c;不管是学习、工作还是平时生活&#xff0c;都能派上用场。但有时候&#xff0c;我们需要把PDF文件里的表格信息转换成Excel格式&#xff0c;这样处理和分析起来更方便。市面上有很多工具…

LabVIEW如何用数字判断布尔数组位置

问&#xff1a;在LabVIEW中&#xff0c;我有一个布尔数组&#xff0c;每次只有一位为True。我想通过判断这个数组对应的数字值来确定哪个位置为True&#xff0c;该如何实现&#xff1f; 答&#xff1a; 你可以将布尔数组转换为一个数字&#xff0c;并通过判断该数字的值来确定…

Java学习中误用 == 比较对象怎么办?

在Java编程中&#xff0c;操作符的误用是一个常见的陷阱&#xff0c;尤其是在比较对象时。理解和正确使用对象的比较机制对编写健壮的、无错误的Java程序至关重要。 一、Java中的操作符 在Java中&#xff0c;操作符用于比较两个变量的值。对于基本数据类型&#xff08;如int、…

element table 表格 span-method 某一列进行相同合并 支持树结构表格

须知 这是 vue2 版本&#xff0c;不过理论上 vue3 也能参考使用 可以直接打开 codepen 查看代码 效果图 代码 打不开 codepen 或者codepen 失效&#xff0c;查看下面代码参考 <script src"//unpkg.com/vue2/dist/vue.js"></script> <script src&…

【加密社】比特币海量数据问题解决方案

加密社 比特币是无敌的存在&#xff0c;刚翻了一遍中本聪的论文&#xff08;其实以前看过一次&#xff0c;那时不明觉厉&#xff09;&#xff0c;发现咱们一直在考虑的问题&#xff0c;基本都能在其论文上找到解决方案了。。 现在出现的这些问题&#xff0c;完全是因为bitcoin…

GS-SLAM论文阅读笔记--GSFusion

介绍 GS-SLAM是最近比较新的方向&#xff0c;由于传统SLAM的研究变得很少&#xff0c;拥抱与新的技术结合的方法也许是个好主意。之前总结了大部分GS-SLAM的文章。但是这个方向在不断发展&#xff0c;而发展初期的很多论文值得参考。所以用博客记录一下比较新的论文阅读笔记。…

代码随想录算法训练营第七天|LeetCode 334.反转字符串、541反转字符串II、151反转字符串中的单词

一、LeetCode 334.反转字符串 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a;编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间&#xff0c;你必须原地修…

万字长文浅谈三高系统建设方法论和实践

1 概述 整个软件的发展历程是一部软件复杂性对抗史&#xff0c;软件的复杂性分为技术复杂性和业务复杂性&#xff0c;业务复杂性主要是建模和抽象设计&#xff0c;技术复杂性主要是三高&#xff08;高性能&#xff0c;高并发&#xff0c;高可用&#xff09;的应对&#xff0c;…

高中生护眼台灯哪个牌子好?五款性价比高的护眼台灯测评结果

现在市面上形形色色的打着“护眼”口号的台灯太多了&#xff0c;因为眼睛对于我们来说很重要&#xff0c;我们看到美丽的事物都因为有他&#xff0c;所以大家一听到护眼就会选择购买。很多商家为了赚钱&#xff0c;随便贴个标签就说护眼&#xff0c;其实一点用都没有。高中生护…