项目:网页制作登录账号、查询单词、返回单词含义(数据库的插入和查找)

一、设计思路流程图

 

 

二、网页代码

①一级页面(denglu.html)

 创建一个.html使用记事本打开,可自己命名(我的为denglu.html)

使用html基础知识完成网页的创建!!!

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>单词含义查询</title>
</head>
<body background = "1.jpg">//自己添加的照片,不添加照片也行
<br><br> <br> <br> <br><br><br> <br> <br> <br><br>
    <h3 align="center"><font color="000000">登录账号</font><h3>
        <form action="./word.html" align="center" method="POST">//post的使用方法,点击登陆后跳转当前目录下的word.html
        <font color="000000">登陆账号: </font><input type="text" placeholder="请输入账号" name="username" required><br>
        <font color="000000">账号密码: </font><input type="password" placeholder="请输入密码" name="password" required><br><br>
        
        <input type="reset" name = "reset">&nbsp&nbsp<input type="submit" value="登录">
        </form>

</body>
</html>

②二级页面(world.html)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>单词含义查询</title>
</head>
<body background = "2.jpg">
<br><br> <br> <br> <br><br><br> <br> <br> <br><br>
    <h3 align="center"><font color="000000">输入要查询的单词</font><h3>
        <form action="./sign.html" align="center"" method="POST">
        <font color="000000">单词: </font><input type="text" placeholder="请输入要查询的单词" name="word" required><br><br><br>
        
        
        <input type="reset" name = "reset">&nbsp&nbsp<input type="submit" value="查询"><br><br><br>
        <button><a href="/.html">返回主页面</button></a><br>
        </form>

</body>
</html>

 

③三级页面(sign.html)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>单词含义查询</title>
</head>
<body background = "4.jpg">
<br><br> <br> <br> <br><br><br> <br> <br> <br><br>
    <h3 align="center"><font color="FFCC66">该单词的含义</font><h3>
        <form action="./word.html" align="center" method="POST">
        <font color="FFCC66">该单词的含义: <br><br><br><br>
        
        
        <input type="submit" value="重新查找单词"><br><br><br><br>

        <button><a href="/.html">返回主页面</button></a><br>

        </form>

</body>
</html>

三、单词和含义插入数据库

①查看文件ditx(1)获取单词和含义

 

 ②插入文件ditx(1)获取单词和含义在数据库中

只插入一次,所以这个代码只使用一次!!!!一次插入结束后,完成后面单词查找的功能

#include "head.h"
#include <sqlite3.h>

int main(int argc, char const *argv[])
{
    long len = 0;
    char cmp[4096] = {0};
    char *name = NULL;
    char *mean = NULL;
    

    FILE *fp = fopen("./dict(1).txt","r");//打开我们的单词文件,使用读的方式
    if(NULL == fp)
    {
        perror("fail to open");
        return -1;
    }


    sqlite3 *q = NULL;
    int ret = sqlite3_open("./info.db",&q);//打开当前目录下info.db数据库
    if(ret != SQLITE_OK)
    {
        fprintf(stderr,"fail sqlite3_open:%s\n",sqlite3_errmsg(q));
        sqlite3_close(q);
        return -1;
    }

    sprintf(cmp,"create table if not exists dict(name char(20),mean char(1024));");
//创建表,一列为name(单词),一列为mean(意义)。if no exists不存的话就创建,存在的话直接插入
    ret = sqlite3_exec(q,cmp,NULL,NULL,NULL);
    if(ret != SQLITE_OK)
    {
        fprintf(stderr,"fail sqlite3_create:%s\n",sqlite3_errmsg(q));
        sqlite3_close(q);
        return -1;
    }
    printf("==============================1\n");
	while(1)//循环插入单词和含义
    {
        char ch[4096] = {0};
        char *p = fgets(ch, sizeof(ch), fp); //fgets接一行
        if(NULL == p)
        {
            break;
        }  
        
        name = strtok(ch," ");//截取前面单词
        mean = strtok(NULL,"\r");//截取后面的单词含义
    
        sprintf(cmp, "insert into dict values( \"%s\", \"%s\");",name,mean);
    //在名为dict的表中插入name和mean;
	    ret = sqlite3_exec(q, cmp, NULL, NULL, NULL);
	    if (ret != SQLITE_OK)
	    {
		    fprintf(stderr, "sqlite3_exec insert: %s\n", sqlite3_errmsg(q));
		    sqlite3_close(q);
		    return -1;
	    }
    }
    fclose(fp);//关闭文件描述符
    sqlite3_close(q);//关闭数据库
    return 0;
}

③检查数据库dict表中单词列数是否一致

四、设计代码dict.c

(sqlite3.c和sqlite3.h自行查找放入当前目录下)

①将html和图片放入当前目录下

 ②完成dixt.c设计

#include "head.h"
#include "sqlite3.h"
int init_tcp_ser(char *ip,unsigned short port)//TCP协议
{
    struct sockaddr_in ser;
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(-1 == sockfd)
    {
        perror("fail sockfd");
        return -1 ;
    }

    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");
		exit(1);
	}
	
	ret = listen(sockfd, 100);

	return sockfd;
}

int recv_http_request(int connfd, char *req_data, int maxlen)//接收对方发来的HTTP报文
{
	memset(req_data, 0, maxlen);
	ssize_t size = recv(connfd, req_data, maxlen, 0);
	if (size < 0)
	{
		perror("fail recv");
		return -1;
	}
	return 0;
}

int prase_http_request(char *req_data, HTTP_REQ_s *http_data)//解析报文
{
	memset(http_data, 0, sizeof(HTTP_REQ_s));
	
	char *ptmp= strtok(req_data, " ");
	if (NULL == ptmp)
	{
		return -1;
	}
	strcpy(http_data->method, ptmp);
	
	ptmp = strtok(NULL, " ");
	if (NULL == ptmp)
	{
		return -1;
	}
	strcpy(http_data->url, ptmp);

	ptmp = strtok(NULL, "\0");
	if (NULL == ptmp)
	{
		return -1;
	}
	
	ptmp = strstr(ptmp, "\r\n\r\n");
	if (NULL == ptmp)
	{
		return -1;
	}
	
	ptmp += 4;
	strcpy(http_data->content, ptmp);

	return 0;
}

int send_http_head(int connfd)//发送报文的头部
{
	char *http_head = "HTTP/1.1 200 OK\r\n"
					  "Content-Type: text/html;charset=UTF-8\r\n"
					  "Connection: close\r\n"
					  "Server: WEB SERVER\r\n\r\n";
	ssize_t size = send(connfd, http_head, strlen(http_head), 0);
	if (size < 0)
	{
		perror("fail send");
		return -1;
	}

	return 0;
}
int send_file(int connfd, char *filename)//发送文件
{
	int fd = open(filename, O_RDONLY);
	if (-1 == fd)
	{
		fprintf(stderr, "fail open: %s\n", filename);
		return -1;
	}
	
	while (1)
	{
		char buff[1024] = {0};
		ssize_t size = read(fd, buff, sizeof(buff));
		if (size <= 0)
		{
			break;
		}
		send(connfd, buff, size, 0);
	}
	
	close(fd);
}
char center[1024] = {0};//全局变量
char *ss = NULL;//全局变量
int flag = -1;//全局变量
int send_http_response(int connfd, HTTP_REQ_s *http_data)
{
	char filename[1024] = {0};
	send_http_head(connfd);
	if (!strcmp(http_data->method, "GET"))
	{
		if (!strcmp(http_data->url, "/"))
		{
			sprintf(filename, "./denglu.html");
		}
		else if (strstr(http_data->url, ".jpg") || strstr(http_data->url, ".png"))
		{
			sprintf(filename, ".%s", http_data->url);//输出自己选用的照片
		}
		else if (!strcmp(http_data->url, "/favicon.ico"))
		{
			return 0;
		}
		else if (!strcmp(http_data->url, "/denglu.html"))
		{
			sprintf(filename, "./denglu.html");//跳转登录页面
		}
	}
	else if (!strcmp(http_data->method, "POST"))
	{
		if (!strcmp(http_data->url, "/word.html"))//如果是POST方法,后面是/word.html
		{
			sprintf(filename, "./word.html");//输出该页面(直接跳转)
		}
		if (!strcmp(http_data->url, "/sign.html"))
		{
			sqlite3 *qdb = NULL;
			int ret = 0; 
			int i = 0;
			char *perrmsg = NULL;
			char cmdbuff[1024] = {0};

			ret = sqlite3_open("./info.db",&qdb);//打开数据库
			if(ret != SQLITE_OK)
        	{
            fprintf(stderr,"sqlite3_open fail :%s\n",sqlite3_errmsg(qdb));
            return -1;
        	}
        	printf("数据库文件打开成功!\n");
        
        	ss = strstr(http_data->content,"=")+1;//将该报文截取,截取需要的单词内容
			printf("===============ss=%s===========\n",ss);
			sprintf(cmdbuff,"select name,mean from dict where name = \"%s\";",ss);//从数据库中选择和name一样的单词,从而找到他的含义
			ret = sqlite3_exec(qdb,cmdbuff,goodsback,NULL,&perrmsg);
			if( ret != SQLITE_OK)
			{
				fprintf(stderr,"sqlite3_exec failed:%s\n",perrmsg);
				sqlite3_free(perrmsg);
				sqlite3_close(qdb);
				return -1;
			}
			if(0 == flag)//定义的全局变量flag,如果变化说明找到该单词
			{
			char head[1024] ={"<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>单词含义查询</title></head><body background = \"4.jpg\"><br><br> <br> <br> <br><br><br> <br> <br> <br><br><h3 align=\"center\"><font color=\"#6F00D2\">该单词的含义</font><h3><form action=\"./word.html\" align=\"center\" method=\"POST\"><font color=\"#6F00D2\">该单词的含义:"};//该html的前面部分
			strcat(head,ss);//将找到的单词拼接在中间
			strcat(head,center);//将单词含义拼接在单词后面
			char end[1024] = {"<br><br><br><br> <input type=\"submit\" value=\"重新查找单词\"><br><br><br><br><button><a href=\"denglu.html\">返回主页面</button></a><br></form></body></html>"};
			strcat(head,end);//将后面的html完成。这样可以不用像一级页面跳转二级页面那样完成跳转页面,直接将页面输入了。
			send(connfd,head,strlen(head),0);//发送该内容
			flag = -1;//将flag重置
			}
			if(-1 == flag)//如果没有找到,中间改变写上未找到该单词
			{
			char head[1024] ={"<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>单词含义查询</title></head><body background = \"4.jpg\"><br><br> <br> <br> <br><br><br> <br> <br> <br><br><h3 align=\"center\"><font color=\"#6F00D2\">该单词的含义</font><h3><form action=\"./word.html\" align=\"center\" method=\"POST\"><font color=\"#6F00D2\">没有该单词!"};
			char end[1024] = {"<br><br><br><br> <input type=\"submit\" value=\"重新查找单词\"><br><br><br><br><button><a href=\"denglu.html\">返回主页面</button></a><br></form></body></html>"};
			strcat(head,end);
			send(connfd,head,strlen(head),0);
			}
			sqlite3_close(qdb);
		}

	}
	send_file(connfd, filename);

	return 0;
}
int goodsback(void *arg,int n ,char **pcontent,char **ptitle)//当数据库打开,条件符合时调用goodsback
{ 
    printf("(char *)arg = %s\n",(char *)arg);
    printf("pcontent[0] = %s\n",pcontent[0]);//因为select了name和mean,两个。所以pcontent[0]为name,pcontent[1]为mean;
	printf("pcontent[1] = %s\n",pcontent[1]);

	printf("n = %d\n",n);
	printf("ss=%s\n",ss);
	if(!strcmp(pcontent[0],ss))//如果名字和搜索的ss符合的话
	{
		sprintf(center,"%s",pcontent[1]);//将改单词含义拼接在中间Center
		flag = 0;
	}
	flag = 0;
    return 0;
}
int add_epoll_fd(int epfd,int fd,uint32_t events)
{
    struct epoll_event ev;
    ev.events = events;
    ev.data.fd = fd;
    int ret = epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev);
    if(-1 == ret)
    {
        perror("fail epoll_ctl add");
        return -1;
    }
}

int delet_epoll_fd(int epfd,int fd)
{
    int ret = epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
    if(-1 == ret)
    {
        perror("epll_ctl del");
        return -1;
    }
    return 0 ;
}

int main(int argc, char const *argv[])
{
    char req_data[1024] = {0};
	HTTP_REQ_s http_data;
    int sockfd = init_tcp_ser("192.168.1.192",8080);//绑定自己的IP地址,端口号
  	struct sockaddr_in cli;
    socklen_t clilen = sizeof(cli);

	int epfd = epoll_create(1024);//完成多个客户端连接,可以忽略,直接发送和接收也行,epoll加不加入都行
    if(-1 == epfd)
    {
        perror("fail epoll_create");
        return -1;
    }

    add_epoll_fd(epfd,sockfd,EPOLLIN);

    struct epoll_event evs[1024];

    while(1)
    {

		int ret = epoll_wait(epfd, evs, 1024, -1);
          if (-1 == ret)
          {
               perror("fail to epoll_wait");
               continue;
          }
          for (int i = 0; i < ret; i++)
          {
               if (sockfd == evs[i].data.fd )
               {
                    int fd_acc = accept(sockfd, (struct sockaddr *)&cli, &clilen);
                    if (-1 == fd_acc)
                    {
                         perror("fail to accept");
                         continue;
                    }
                    add_epoll_fd(epfd, fd_acc, EPOLLIN);
                    char usertmp[4096] = {0};
                    sprintf(usertmp,"IP:%s PORT:%d已连接\n", inet_ntoa(cli.sin_addr), ntohs(cli.sin_port));
               }
               else
               {
                    char tmpbuff[4096 * 2] = {0};
					memset(tmpbuff, 0, sizeof(tmpbuff));
					int nsize = recv_http_request(evs[i].data.fd,tmpbuff,1024);
                    if (nsize < 0)
                    {
                         perror("fail to recv");
                         delet_epoll_fd(epfd, evs[i].data.fd);
                         close(evs[i].data.fd); 
                         continue;
                    }
					prase_http_request(tmpbuff,&http_data);//解析
					int cont  = send_http_response(evs[i].data.fd, &http_data);//发送报文
                    
					if (-1 == cont)
                    {
                         delet_epoll_fd(epfd, evs[i].data.fd);
                         close(evs[i].data.fd);
                         continue;
                    }	
					close(evs[i].data.fd);
					continue;
			   }

		  
		}
	}
	close(sockfd);
    return 0;
}

也可以分成几个.c来写,一个.c文件看起来比较多,其实需要写的,比较难的只有中间部分的数据库查找

③makefile

OBJ:=main
OBJS+=dict.c
OBJS+=sqlite3.o

$(OBJ):$(OBJS)
    gcc $^ -o $@ -lpthread -ldl
%.o:%.c
    gcc -c $^ -o $@
.PHONY:
clean:
        rm $(OBJ)

④运行结果展示

发布的视频中(7月25日)

2023年7月25日

五、头文件

#ifndef __HEAD_H__//防止头文件被重复定义
#define __HEAD_H__//防止头文件被重复定义

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <poll.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <signal.h>
#include <sys/epoll.h>

typedef struct http
{
    char method[32];     //请求方法
    char url[512];       //请求的内容URL
    char content[1024];  //请求报文中的正文
}HTTP_REQ_s;


extern int goodsback(void *arg,int n ,char **pcontent,char **ptitle);
#endif//防止头文件被重复定义

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值