嵌入式在线商城

一、主线功能

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;
}

五、网页效果

  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值