客户端访问网页,发送请求报文,服务端根据对方的请求报文,发送各种内容
主要负责网络通信
#include<sqlite3.h>
#include"../include/net.h"
#include"../include/log.h"
int init_tcp_ser(const char *ip,unsigned short port)
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
{
perror("fail socket");
return -1;
}
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(ret < 0)
{
perror("fail bind");
return -1;
}
ret = listen(sockfd,1024);
if(ret < 0)
{
perror("fail listen");
return -1;
}
write_log(LOG_INFO,"tcp初始化");
return sockfd;
}
int recv_http_request(int connfd,char *req,int maxlen)
{
memset(req,0,maxlen);
ssize_t size = recv(connfd,req,maxlen,0);
if(size < 0)
{
perror("fail recv");
return size;
}
write_log(LOG_INFO,"接收响应报文");
return size;
}
int parse_http_request(char *req,req_t *phreq)
{
memset(phreq,0,sizeof(req_t));
char *p = strtok(req," ");
if(NULL == p)
{
return -1;
}
strcpy(phreq -> method,p);
p = strtok(NULL," ");
if(NULL == p)
{
return -1;
}
strcpy(phreq -> url,p);
p = strtok(NULL,"\0");
if(NULL == p)
{
return -1;
}
p = strstr(p,"\r\n\r\n");
if(NULL == p)
{
return -1;
}
strcpy(phreq -> content,p + 4);
write_log(LOG_INFO,"解码中");
return 0;
}
int send_http_request_head(int connfd)
{
char *presp = "HTTP/1.1 200 0K\r\n"
"Content-Type: text/html;charset=utf-8\r\n"
"Server:openresty\r\n"
"Connection:keep-alive\r\n\r\n";
ssize_t size = send(connfd,presp,strlen(presp),0);
if(size < 0)
{
perror("fail send");
return -1;
}
write_log(LOG_INFO,"发送响应报文");
return 0;
}
int send_net_file(int connfd,char *filename)
{
char buff[1024] = {0};
int fd = open(filename,O_RDONLY);
if(fd < 0)
{
perror("fail open");
return -1;
}
while(1)
{
memset(buff,0,sizeof(buff));
ssize_t size = read(fd,buff,sizeof(buff));
if(size <= 0)
{
break;
}
send(connfd,buff,size,0);
}
write_log(LOG_INFO,"发送文件");
close(fd);
return 0;
}
int send_http_response(int connfd,req_t *phreq)
{
char filename[512] = {0};
send_http_request_head(connfd);
if(!strcmp(phreq -> method,"GET"))
{
if(!strcmp(phreq -> url,"/"))
{
sprintf(filename,"./html/1.html");
send_net_file(connfd,filename);
}
else if(!strcmp(phreq -> url,"/favicon.ico"))
{
return 0;
}
else if(strstr(phreq -> url,".jpg") || strstr(phreq -> url,".png"))
{
sprintf(filename,".%s",phreq -> url);
send_net_file(connfd,filename);
}
else if(strstr(phreq -> url,".html"))
{
char path[64] = {0};
memset(path,0,sizeof(path));
strcpy(path,phreq -> url);
sprintf(filename,"./html/mean.html");
send_net_file(connfd,filename);
find1(atoi(phreq->url+11),connfd);
}
}
else if(!strcmp(phreq -> method,"POST"))
{
if(strstr(phreq -> url,".html"))
{
if(!strcmp(phreq ->url , "/goods.html"))
{
sprintf(filename,"./html%s",phreq -> url);
send_net_file(connfd,filename);
find(phreq->content,connfd);
}
else
{
sprintf(filename,"./html%s",phreq -> url);
send_net_file(connfd,filename);
}
}
}
return 0;
}
此模块用于在数据库中寻找指定商品
#include<sqlite3.h>
#include"../include/net.h"
unsigned char FromHex(unsigned char x)
{
if(0 == x ) return -1;
unsigned char y;
if(x>='A' &&x<='Z') y = x-'A'+10;
else if(x>='a' &&x <='z') y = x-'a'+10;
else if(x>='0' && x<='9') y = x-'0';
return y;
}
int urlDecode( char* dest, const char* src)
{
if(NULL ==src || NULL == dest)
{
return -1;
}
int len = strlen(src);
int i =0 ;
for(i = 0 ;i<len;i++)
{
if('+' == src[i]) strcat(dest,"");
else if('%'==src[i])
{
//if(i+2len)return -1;
unsigned char high = FromHex((unsigned char)src[++i]);
unsigned char low = FromHex((unsigned char)src[++i]);
unsigned char temp = high*16 +low;
char temp2[5]={0};
sprintf(temp2,"%c",temp);
strcat(dest , temp2);
}
}
return 0;
}
int callback(void *arg,int n,char **value,char **name)
{
int connfd = *(int *)arg;
char buff[1024] = {0};
{
sprintf(buff,"<tr><td><a href =\"mean.html?%s\" method=\"POST\"><img border=\"0\"src=\"./source/%s\"alt=\"%s\"width=\"100\"height=\"100\"></a></td>><td>%s</td></tr>",value[0],value[20],"goods.html",value[3]);
}
send(connfd,buff,strlen(buff),0);
return 0;
}
int find(char *phone,int connfd)
{
sqlite3 *pdb;
int ret = sqlite3_open("./source/123.db",&pdb);
if(ret != SQLITE_OK)
{
fprintf(stderr,"fail open:%s\n",sqlite3_errmsg(pdb));
return -1;
}
char new_buff[128] ={0};
char size[1024] = {0};
urlDecode(new_buff,phone);
sprintf(size,"select * from goods where goods_name like \"%s%%\";",new_buff);
ret = sqlite3_exec(pdb,size,callback,&connfd,NULL);
if(ret != SQLITE_OK)
{
fprintf(stderr,"fail sqlite3_exec:%s\n",sqlite3_errmsg(pdb));
return -1;
}
sqlite3_close(pdb);
return 0;
}
int callback1(void *arg,int n,char **value,char **name)
{
int connfd = *(int *)arg;
char buff[102400] = {0};
{
printf("%s=%s\n",name[3],value[3]);
sprintf(buff,"<img src=\"../source/%s\" alt=\"商品\" class=\"product-image\"><h1 class=\"product-title\">%s</h1><p class=\"product-description\">%s</p ><p class=\"p\">市场价格:%s</p ><p class=\"product-price\">商场价格:%s</p ></div></body></html>",value[20],value[3],value[18],value[10],value[11]);
}
send(connfd,buff,strlen(buff),0);
return 0;
}
int find1(int id,int connfd)
{
printf("id = %d",id);
sqlite3 *pdb;
int ret = sqlite3_open("./source/123.db",&pdb);
if(ret != SQLITE_OK)
{
fprintf(stderr,"fail open:%s\n",sqlite3_errmsg(pdb));
return -1;
}
char size[1024] = {0};
sprintf(size,"select * from goods where goods_id=\"%d\";",id);
printf("size =%s\n",size);
ret = sqlite3_exec(pdb,size,callback1,&connfd,NULL);
if(ret != SQLITE_OK)
{
fprintf(stderr,"fail sqlite3_exec:%s\n",sqlite3_errmsg(pdb));
return -1;
}
epooll模块
#include"../include/net.h"
int epoll_add_fd(int eptds ,int fd, uint32_t events)
{
struct epoll_event ev;
ev.events = events;
ev.data.fd = fd;
int ret = epoll_ctl(eptds,EPOLL_CTL_ADD,fd,&ev);
if(ret < 0)
{
perror("fail epoll_ctl add");
return -1;
}
return 0;
}
int epoll_DEL_fd(int eptds ,int fd, uint32_t events)
{
struct epoll_event ev;
ev.events = events;
ev.data.fd = fd;
int ret = epoll_ctl(eptds,EPOLL_CTL_DEL,fd,&ev);
if(ret < 0)
{
perror("fail epoll_ctl add");
return -1;
}
return 0;
}
日志模块
"../include/log.h"
#include <sys/stat.h>
#include <sys/types.h>
log_s log_g;//全局结构体变量
int init_log()//初始化函数
{
struct tm *ptm = NULL;
time_t sec = time(NULL);
ptm = localtime(&sec);
log_g.time = *ptm;
char filename[256] = {0};//村名字进去不能用char*
mkdir("LOG",0777);//创建目录
sprintf(filename,"./LOG/log%d-%02d-%02d.txt",ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday);//在LOG目录下创建文件
log_g.fp = fopen(filename,"a");
if(log_g.fp == NULL)
{
printf("fopen fail!\n");
return -1;
}
return 0;
}
int write_log(log_lev lev,char *str)
{
time_t sec = time(NULL);
struct tm *ptm = NULL;
ptm = localtime(&sec);
if(ptm->tm_mday != log_g.time.tm_mday)
// if(ptm->tm_min != log_g.time.tm_min)
{
deinit_log();
init_log();
}
char *leves[3] = {"LOG_INFO","LOG_WARN","LOG_ERR"};//由于枚举成员本质是整数,传递不了他代表的字符串,创建字符串数组,用枚举常量表示下标;
fprintf(log_g.fp,"[%d-%d-%d %d:%d;%d][%s]%s\n",ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday,
ptm->tm_hour,ptm->tm_min,ptm->tm_sec,leves[lev],str);
fflush(log_g.fp);
return 0;
}
void deinit_log()
{
fclose(log_g.fp);
}
多路tcp
main函数
#include"../include/net.h"
#include "../include/log.h"
int main(int argc,char *argv[])
{
init_log();
write_log(LOG_INFO,"日志模块初始化成功!");
char req[1024] = {0};
req_t hreq;
int sockfd = init_tcp_ser("192.168.0.179",8080);
if (sockfd < 0)
{
return -1;
}
int maxfd = 0;
int epfds = epoll_create(10000);//创建描述符集合最大10
if(epfds < 0)
{
perror("fail epoll_create");
return -1;
}
//添加描述符
epoll_add_fd(epfds,sockfd,EPOLLIN);
struct epoll_event evs[10];
while(1)
{
#if 0
int connfd = accept(sockfd,NULL,NULL);
if(connfd < 0)
{
perror("fail accept");
return -1;
write_log(LOG_ERR,"accept失败!");
}
write_log(LOG_INFO,"与客户端accept成功");
int ret = recv_http_request(connfd,req,sizeof(req));//不传长度指针无法计算长度
if(ret < 0)
{
return -1;
}
ret = parse_http_request(req,&hreq);
if(ret < 0)
{
return -1;
}
printf("method : %s\n", hreq.method);
printf("url: %s\n", hreq.url);
printf("content : %s\n", hreq.content);
send_http_response(connfd, &hreq);
close(connfd);
#endif
int cnt = epoll_wait(epfds,evs,10,-1);
if(cnt < 0)
{
perror("fail epoll wait");
return -1;
}
for(int i = 0;i <cnt;i++)
{
if(evs[i].data.fd==sockfd)
{
int connfd=accept(sockfd,NULL,NULL);
if(connfd < 0)
{
write_log(LOG_ERR,"accept失败!");
perror("fail accept");
return -1;
}
write_log(LOG_INFO,"与客户端accept成功");
epoll_add_fd(epfds,connfd,EPOLLIN);
write_log(LOG_INFO,"epoll添加套接字");
}
else
{
printf("connfd_evs= %d\n",evs[i].data.fd);
int ret = recv_http_request(evs[i].data.fd,req,sizeof(req));//不传长度指针无法计算长度
if(ret < 0)
{
return -1;
}
ret = parse_http_request(req,&hreq);
if(ret < 0)
{
return -1;
}
printf("method : %s\n", hreq.method);
printf("url: %s\n", hreq.url);
printf("content : %s\n", hreq.content);
send_http_response(evs[i].data.fd, &hreq);
epoll_DEL_fd(epfds,evs[i].data.fd,EPOLLIN);
write_log(LOG_INFO,"epoll删除套接字");
close(evs[i].data.fd);
}
}
}
close(sockfd);
return 0;
}
以及HTML文件