http协议
URL
在WWW上,每一信息资源都有统一的且在网上唯一的地址,该地址就叫URL(Uniform Resource Locator,统一资源定位符),就是指网络地址。
请求消息 - 浏览器发送给服务器
四部分:
请求行:
请求说明类型:
GET:请求指定的页面信息,并返回实体主体
POST:向指定资源提交数据进行处理请求。数据被包含在请求体中,POST可能会导致新的资源的建立或者已有资源的修改。
访问的资源,以及使用的http版本
eg:
GET /*.TXT /HTTP1.1\r\n; //中间要空格 结尾有\r\n
请求头:
说明服务器要使用的附加信息。(不重要)
空行:
r\n 必须有
请求的数据:
可有可无(当为GET就一定没有,当为POST时就为请求行的第二部分/.*TXT)
响应消息 - 服务器给浏览器发
四部分:
状态行:
http协议版本号,状态码,状态信息
eg: HTTP1.1 200 OK
消息报头:
空行:
响应正文:
请求的数据
正则表达式
#define MAX 1024
void epoll_run(int port)
{
//创建一个根节点
int epfd = epoll_create(MAX);
//添加监听的节点
int lfd = init_lfd;
//等待事件
struct epoll_event all[MAX];
while(1){
int ret = epoll_wait(epfd,all,MAX,-1);
for(int i = 0; i < ret; ++i){
struct epoll_event *p = &all[i];
if(!(p->events & EPOLLIN)){
continue;//不是读事件 默认不处理
}
if(pev->data.fd == lfd){
do_accept(epfd,lfd);
}else {
}
}
}
}
void do_read(int cfd)
{
char buf[1024];
get_line(cfd,buf,sizeof(buf));
if(strcasecmp("get",buf) == 0){
http_request(buf,cfd);
}
}
void http_request(const char *buf,int cfd)
{
char method[12],path[1024],protocol[12];
sscanf(buf,"%[^ ] %[^ ] %[^ ]",method,path,protocol);
//转码 将不能识别的中文乱码 - > 中文
//解码
decode_str(path,path);
char *file = path + 1;
//若果没有指定访问资源,默认显式资源目录内容
if(strcmp(path,"/") == 0){
file = "./";//就是资源目录的当前位置
}
//获取文件属性
struct stat st;
int ret = stat(file,&st);
//判断是目录还是文件
if(S_ISDIR(st.st_mode))
{
//是目录
//报头
send_respond_head(cfd,200,"OK","text/html",-1);
//发送目录
send_dir(cfd,file);
}
else if(S_ISREG(st.st_mode))
{
//是文件
//发送消息报头
send_respond_head(cfd,200,"OK","text/plain",st.st_size());
//发送文件内容
send_file(cfd,file);
}
}
void send_dir(int cfd, const char *dirname)
{
//拼凑一个html页面
char ebuf[4096];
char buf[4096];
sprintf(buf,"<html><head><title>目录名:%s</title></head>",dirname);
char path[1024];
#if 0
DIR *dir = opendir(dirname);//打开目录
struct dirent* ptr = NULL;
while((ptr = readdir(dir)) != NULL){
char *name = ptr->d_name;
//这里再写到html中
}
close(dir);//第一种方式
#endif
struct dirent** ptr;
int len = scandir(dirname,&ptr,NULL,alphasort);//返回值为有多少个文件
for(int i = 0; i < len; i++){
char *name = ptr[i]->d_name;
sprintf(path,"%s/%s",dirname,name);
struct stat st;
stat(path,&st);
//转码
encode(ebuf,sizeof(ebuf),name);
if(S_ISREG(st.st_mode)){
sprintf(buf+strlen(buf),"<tr><td><a herf=\"%s\">%s</a></td><td>%ld</td></tr>",ebuf,name,(long)st.st_size);
}
else if(S_ISDIR(st.st_mode)){
sprintf(buf+strlen(buf),"<tr><td><a herf=\"%s/\">%s/</a></td><td>%ld</td></tr>",ebuf,name,(long)st.st_size);
}
send(cfd, buf, sizeof(buf), 0);
memset(buf, 0, sizeof(buf));
}
sprintf(buf+strlen(buf),"</table></body></html>");
send(cfd, buf, sizeof(buf), 0);
}
void send_respond_head(int cfd,int no,const char *desp,const char *type,long len)
{
char buf[1024];
//状态行
sprintf(buf,"http/1.1 %d %s\r\n",no,desp);
send(cfd,buf,sizeof(buf),0);
//消息报头
sprintf(buf,"Content-Type:%s\r\n",type);
sprintf(buf+strlen(buf),"Content-Length:%ld\r\n",len);
send(cfd,buf,sizeof(buf),0);
//空行
send(cfd,"\r\n",2,0);
}
void send_file(int cfd,const char* file)
{
//打开文件
int fd = open(file,O_RDONLY);
char buf[4096];
int len = 0;
while((len = read(fd,buf,sizeof(buf))) > 0){
send(cfd,buf,len,0);
}
close(fd);
}
int get_line(int sock,char *str,int size)
{
int i = 0;
char c = '\0';
int n;
while((i < size - 1) && (c != '\n')){
n = recv(sock,&c,1,0);
if(n > 0){
if(c == '\r'){
n = recv(sock,&c,1,MSG_PEEK);
if((n > 0) && (c == '\n')){
recv(sock,&c,1,0);
}
else {
c = '\n';
}
}
str[i] = c;
++i;
}
else {
c = '\n';
}
}
str[i] = '\0';
return i;
}
void do_accept(int epfd,int lfd)
{
struct sockaddr_in cile;
socklen_t cile_t = sizeof(cile);
int cfd = accept(lfd,(struct sockaddr *)&cile,&cile_t);
int flag = fcntl(cfd,F_GETFL);
flag |= O_NONBLOCK;
fcntl(cfd,F_SETFL,flag);//设置边沿非阻塞
struct epoll_event ev;
ev.data.fd = cfd;
ev.events = EPOLLIN | EPOLLET;//边沿非阻塞
epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);
}
int init_lfd(int epfd,int port)
{
int lfd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(port);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(lfd,(struct sockaddr *)&serv,sizeof(serv));
listen(lfd,128);
epoll_add(epfd,)
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = lfd;
epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);
return lfd;
}