实现效果如下:
图片可以直接显示
cpp h 这些可以直接显示 其他的 则是提示是否要下载
单线程 还有bug
代码如下 先放上来
#include "httpserver.h"
#include "stdio.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BURSIZE 1024
int hex2dec(char c)
{
if ('0' <= c && c <= '9') {
return c - '0';
} else if ('a' <= c && c <= 'f') {
return c - 'a' + 10;
} else if ('A' <= c && c <= 'F') {
return c - 'A' + 10;
} else {
return -1;
}
}
char dec2hex(short int c)
{
if (0 <= c && c <= 9) {
return c + '0';
} else if (10 <= c && c <= 15) {
return c + 'A' - 10;
} else {
return -1;
}
}
/*
* 编码一个url
*/
void urlencode(char url[])
{
int i = 0;
int len = strlen(url);
int res_len = 0;
char res[BURSIZE];
for (i = 0; i < len; ++i) {
char c = url[i];
if (('0' <= c && c <= '9') ||
('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') || c == '/' || c == '.') {
res[res_len++] = c;
} else {
int j = (short int)c;
if (j < 0)
j += 256;
int i1, i0;
i1 = j / 16;
i0 = j - i1 * 16;
res[res_len++] = '%';
res[res_len++] = dec2hex(i1);
res[res_len++] = dec2hex(i0);
}
}
res[res_len] = '\0';
strcpy(url, res);
}
/*
* 解码url
*/
void urldecode(char url[])
{
int i = 0;
int len = strlen(url);
int res_len = 0;
char res[BURSIZE];
for (i = 0; i < len; ++i) {
char c = url[i];
if (c != '%') {
res[res_len++] = c;
} else {
char c1 = url[++i];
char c0 = url[++i];
int num = 0;
num = hex2dec(c1) * 16 + hex2dec(c0);
res[res_len++] = num;
}
}
res[res_len] = '\0';
strcpy(url, res);
}
int CreateSocketFD()
{
int fd = 0;
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd == -1)
{
perror("Scoket fd = -1");
return 0;
}
int reuseport = 1;
int ret = setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuseport,sizeof(reuseport));
if(ret == -1)
{
perror("setsocketopt failed");
return -1;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(fd,(struct sockaddr*)&addr,sizeof(addr));
if(ret == -1)
{
perror("bind error");
return -1;
}
ret = listen(fd,10);
if(ret == -1)
{
perror("listen error ");
return -1;
}
return fd;
}
int AcceptClients(int epoll_fd,int fd)
{
struct sockaddr addr;
int cfd = accept(fd,NULL,NULL);
if(cfd == -1)
{
perror("accept failed");
}
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;
int ret = epoll_ctl(epoll_fd,EPOLL_CTL_ADD,cfd,&ev);
if(ret == -1)
{
perror("epoll ctl failed");
return 0;
}
return 0;
}
const char *GetFileType(const char *filename)
{
const char *dot = strrchr(filename,'.');
if(dot == NULL)
{
return "text/plain; charset=utf-8";
}
if(strcmp(dot,".jpg") == 0 ||strcmp(dot,".jpeg") == 0)
{
return "image/jpg";
}
if(strcmp(dot,".html") == 0 ||strcmp(dot,".htm") == 0)
{
return "text/html; charset=utf-8";
}
if(strcmp(dot,".png") == 0)
{
return "image/png";
}
if(strcmp(dot,".bmp") == 0)
{
return "image/bmp";
}
if(strcmp(dot,".gif") == 0)
{
return "image/gif";
}
if(strcmp(dot,".css") == 0)
{
return "text/css";
}
if(strcmp(dot,".mp3") == 0)
{
return "audio/mpeg";
}
return "text/plain; charset=utf-8";
}
int SendHead(int cfd,int status ,const char *desc,const char *type,int size)
{
char buf[4096] = {0};
sprintf(buf,"http/1.1 %d %s\r\n",status,desc);
sprintf(buf+strlen(buf),"content-type: %s\r\n",type);
sprintf(buf+strlen(buf),"content-length: %d\r\n\r\n",size);
printf("SendHead buf[%s]\n",buf);
send(cfd,buf,strlen(buf),0);
return 0;
}
int SendDir(const char *dirname,int cfd)
{
char buf[4096] = {0};
sprintf(buf,"%s ",dirname);
printf("SendDir dirname=[%s]\n",dirname);
struct dirent **namelist;
int count = scandir(dirname,&namelist,NULL,alphasort);
printf("SendDir count=[%d]\n",count);
for(int i = 0;i< count;i++)
{
char *name = namelist[i]->d_name;
struct stat st;
char sub_path[1024]={0};
sprintf(sub_path,"%s/%s",dirname,name);
stat(sub_path,&st);
if(S_ISDIR(st.st_mode))
{
sprintf(buf+strlen(buf),
"%s %ld ",name,name,st.st_size);
}
else
{
sprintf(buf+strlen(buf),
"%s %ld ",name,name,st.st_size);
}
printf("cfd:%d Sendbuf[%s]\n",cfd,buf);
send(cfd,buf,strlen(buf),0);
memset(buf,0,sizeof(buf));
free(namelist[i]);
}
sprintf(buf,"
");
printf("cfd:%d Sendbuf[%s]\n",cfd,buf);
send(cfd,buf,strlen(buf),0);
free(namelist);
return 0;
}
int SendFile(const char* filename,int cfd)
{
int fd = open(filename,O_RDONLY);
if(fd >0)
{
#if 0
while(1)
{
char buf[1024];
int len = read(fd,buf,sizeof buf);
if(len >0)
{
send(cfd,buf,len,0);
usleep(10);
}
else if(len == 0)
{
printf("Read file end\n");
break;
}
else
{
perror("read error");
}
}
#else
off_t offset = 0;
int file_size = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
while(offset 0)
{
if(total+read_len