2 Star 2 Fork 0

SmithGoll / c语言学习

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
httpserver-latest.c 12.47 KB
一键复制 编辑 原始数据 按行查看 历史
SmithGoll 提交于 2022-03-31 05:22 . 更新
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<strings.h>
#include<ctype.h>
#define send_msg(x,y) send(x,y,sizeof(y) - 1,0)
#define BUF_SIZE 1024
/*
#define USEOLD
*/
typedef int fd_t;
const char header[] = {
"HTTP/1.1 200 OK\r\n"
"Server: Goll's tiny web server\r\n"
"Connection: close\r\n"
"Content-Type: "
};
const char bad_request[] = {
"HTTP/1.1 400 BAD REQUEST\r\n"
"\r\n"
};
const char method_not_supported[] = {
"HTTP/1.1 501 Method Not Implemented\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<HTML><HEAD><TITLE>Method Not Implemented\r\n"
"</TITLE></HEAD>\r\n"
"<BODY><P>HTTP request method not supported.\r\n"
"</BODY></HTML>\r\n"
};
const char not_found[] = {
"HTTP/1.1 404 NOT FOUND\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<HTML><TITLE>Not Found</TITLE>\r\n"
"<BODY><P>The server could not fulfill\r\n"
"your request because the resource specified\r\n"
"is unavailable or nonexistent.\r\n"
"</BODY></HTML>\r\n"
};
/*
这是类型处理的代码
还可以有所改进
现在先晒出来
*/
const char * bin_type = "application/octet-stream";
struct type_list
{
const char * suffix;
int suffix_len;
const char * mime_type;
} list[] = {
{"ai" , 2 , "application/postscript"},
{"aif" , 3 , "audio/x-aiff"},
{"aifc" , 4 , "audio/x-aiff"},
{"aiff" , 4 , "audio/x-aiff"},
{"arj" , 3 , "application/x-arj-compressed"},
{"asc" , 3 , "text/plain"},
{"asf" , 3 , "video/x-ms-asf"},
{"asx" , 3 , "video/x-ms-asx"},
{"au" , 2 , "audio/ulaw"},
{"avi" , 3 , "video/x-msvideo"},
{"bat" , 3 , "application/x-msdos-program"},
{"bcpio" , 5 , "application/x-bcpio"},
{"bin" , 3 , "application/octet-stream"},
{"c" , 1 , "text/plain"},
{"cc" , 2 , "text/plain"},
{"ccad" , 4 , "application/clariscad"},
{"cdf" , 3 , "application/x-netcdf"},
{"class" , 5 , "application/octet-stream"},
{"cod" , 3 , "application/vnd.rim.cod"},
{"com" , 3 , "application/x-msdos-program"},
{"cpio" , 4 , "application/x-cpio"},
{"cpt" , 3 , "application/mac-compactpro"},
{"csh" , 3 , "application/x-csh"},
{"css" , 3 , "text/css"},
{"dcr" , 3 , "application/x-director"},
{"deb" , 3 , "application/x-debian-package"},
{"dir" , 3 , "application/x-director"},
{"dl" , 2 , "video/dl"},
{"dms" , 3 , "application/octet-stream"},
{"doc" , 3 , "application/msword"},
{"drw" , 3 , "application/drafting"},
{"dvi" , 3 , "application/x-dvi"},
{"dwg" , 3 , "application/acad"},
{"dxf" , 3 , "application/dxf"},
{"dxr" , 3 , "application/x-director"},
{"eps" , 3 , "application/postscript"},
{"etx" , 3 , "text/x-setext"},
{"exe" , 3 , "application/octet-stream"},
{"ez" , 2 , "application/andrew-inset"},
{"f" , 1 , "text/plain"},
{"f90" , 3 , "text/plain"},
{"fli" , 3 , "video/fli"},
{"flv" , 3 , "video/flv"},
{"gif" , 3 , "image/gif"},
{"gl" , 2 , "video/gl"},
{"gtar" , 4 , "application/x-gtar"},
{"gz" , 2 , "application/x-gzip"},
{"hdf" , 3 , "application/x-hdf"},
{"hh" , 2 , "text/plain"},
{"hqx" , 3 , "application/mac-binhex40"},
{"h" , 1 , "text/plain"},
{"htm" , 3 , "text/html;charset=utf-8"},
{"html" , 4 , "text/html;charset=utf-8"},
{"ice" , 3 , "x-conference/x-cooltalk"},
{"ief" , 3 , "image/ief"},
{"iges" , 4 , "model/iges"},
{"igs" , 3 , "model/iges"},
{"ips" , 3 , "application/x-ipscript"},
{"ipx" , 3 , "application/x-ipix"},
{"jad" , 3 , "text/vnd.sun.j2me.app-descriptor"},
{"jar" , 3 , "application/java-archive"},
{"jpeg" , 4 , "image/jpeg"},
{"jpe" , 3 , "image/jpeg"},
{"jpg" , 3 , "image/jpeg"},
{"js" , 2 , "application/x-javascript"},
{"kar" , 3 , "audio/midi"},
{"latex" , 5 , "application/x-latex"},
{"lha" , 3 , "application/octet-stream"},
{"lsp" , 3 , "application/x-lisp"},
{"lzh" , 3 , "application/octet-stream"},
{"m" , 1 , "text/plain"},
{"m3u" , 3 , "audio/x-mpegurl"},
{"man" , 3 , "application/x-troff-man"},
{"me" , 2 , "application/x-troff-me"},
{"mesh" , 4 , "model/mesh"},
{"mid" , 3 , "audio/midi"},
{"midi" , 4 , "audio/midi"},
{"mif" , 3 , "application/x-mif"},
{"mime" , 4 , "www/mime"},
{"movie" , 5 , "video/x-sgi-movie"},
{"mov" , 3 , "video/quicktime"},
{"mp2" , 3 , "audio/mpeg"},
{"mp2" , 3 , "video/mpeg"},
{"mp3" , 3 , "audio/mpeg"},
{"mpeg" , 4 , "video/mpeg"},
{"mpe" , 3 , "video/mpeg"},
{"mpga" , 4 , "audio/mpeg"},
{"mpg" , 3 , "video/mpeg"},
{"ms" , 2 , "application/x-troff-ms"},
{"msh" , 3 , "model/mesh"},
{"nc" , 2 , "application/x-netcdf"},
{"oda" , 3 , "application/oda"},
{"ogg" , 3 , "application/ogg"},
{"ogm" , 3 , "application/ogg"},
{"pbm" , 3 , "image/x-portable-bitmap"},
{"pdb" , 3 , "chemical/x-pdb"},
{"pdf" , 3 , "application/pdf"},
{"pgm" , 3 , "image/x-portable-graymap"},
{"pgn" , 3 , "application/x-chess-pgn"},
{"pgp" , 3 , "application/pgp"},
{"pl" , 2 , "application/x-perl"},
{"pm" , 2 , "application/x-perl"},
{"png" , 3 , "image/png"},
{"pnm" , 3 , "image/x-portable-anymap"},
{"pot" , 3 , "application/mspowerpoint"},
{"ppm" , 3 , "image/x-portable-pixmap"},
{"pps" , 3 , "application/mspowerpoint"},
{"ppt" , 3 , "application/mspowerpoint"},
{"ppz" , 3 , "application/mspowerpoint"},
{"pre" , 3 , "application/x-freelance"},
{"prt" , 3 , "application/pro_eng"},
{"ps" , 2 , "application/postscript"},
{"qt" , 2 , "video/quicktime"},
{"ra" , 2 , "audio/x-realaudio"},
{"ram" , 3 , "audio/x-pn-realaudio"},
{"rar" , 3 , "application/x-rar-compressed"},
{"ras" , 3 , "image/cmu-raster"},
{"ras" , 3 , "image/x-cmu-raster"},
{"rgb" , 3 , "image/x-rgb"},
{"rm" , 2 , "audio/x-pn-realaudio"},
{"roff" , 4 , "application/x-troff"},
{"rpm" , 3 , "audio/x-pn-realaudio-plugin"},
{"rtf" , 3 , "application/rtf"},
{"rtf" , 3 , "text/rtf"},
{"rtx" , 3 , "text/richtext"},
{"scm" , 3 , "application/x-lotusscreencam"},
{"set" , 3 , "application/set"},
{"sgml" , 4 , "text/sgml"},
{"sgm" , 3 , "text/sgml"},
{"sh" , 2 , "application/x-sh"},
{"shar" , 4 , "application/x-shar"},
{"silo" , 4 , "model/mesh"},
{"sit" , 3 , "application/x-stuffit"},
{"skd" , 3 , "application/x-koan"},
{"skm" , 3 , "application/x-koan"},
{"skp" , 3 , "application/x-koan"},
{"skt" , 3 , "application/x-koan"},
{"smi" , 3 , "application/smil"},
{"smil" , 4 , "application/smil"},
{"snd" , 3 , "audio/basic"},
{"sol" , 3 , "application/solids"},
{"spl" , 3 , "application/x-futuresplash"},
{"src" , 3 , "application/x-wais-source"},
{"step" , 4 , "application/STEP"},
{"stl" , 3 , "application/SLA"},
{"stp" , 3 , "application/STEP"},
{"sv4cpio" , 7 , "application/x-sv4cpio"},
{"sv4crc" , 6 , "application/x-sv4crc"},
{"svg" , 3 , "image/svg+xml"},
{"swf" , 3 , "application/x-shockwave-flash"},
{"t" , 1 , "application/x-troff"},
{"tar" , 3 , "application/x-tar"},
{"tcl" , 3 , "application/x-tcl"},
{"tex" , 3 , "application/x-tex"},
{"texi" , 4 , "application/x-texinfo"},
{"texinfo" , 7 , "application/x-texinfo"},
{"tgz" , 3 , "application/x-tar-gz"},
{"tiff" , 4 , "image/tiff"},
{"tif" , 3 , "image/tiff"},
{"tr" , 2 , "application/x-troff"},
{"tsi" , 3 , "audio/TSP-audio"},
{"tsp" , 3 , "application/dsptype"},
{"tsv" , 3 , "text/tab-separated-values"},
{"txt" , 3 , "text/plain"},
{"unv" , 3 , "application/i-deas"},
{"ustar" , 5 , "application/x-ustar"},
{"vcd" , 3 , "application/x-cdlink"},
{"vda" , 3 , "application/vda"},
{"viv" , 3 , "video/vnd.vivo"},
{"vivo" , 4 , "video/vnd.vivo"},
{"vrml" , 4 , "model/vrml"},
{"vsix" , 4 , "application/vsix"},
{"wav" , 3 , "audio/x-wav"},
{"wax" , 3 , "audio/x-ms-wax"},
{"wiki" , 4 , "application/x-fossil-wiki"},
{"wma" , 3 , "audio/x-ms-wma"},
{"wmv" , 3 , "video/x-ms-wmv"},
{"wmx" , 3 , "video/x-ms-wmx"},
{"wrl" , 3 , "model/vrml"},
{"wvx" , 3 , "video/x-ms-wvx"},
{"xbm" , 3 , "image/x-xbitmap"},
{"xlc" , 3 , "application/vnd.ms-excel"},
{"xll" , 3 , "application/vnd.ms-excel"},
{"xlm" , 3 , "application/vnd.ms-excel"},
{"xls" , 3 , "application/vnd.ms-excel"},
{"xlw" , 3 , "application/vnd.ms-excel"},
{"xml" , 3 , "text/xml"},
{"xpm" , 3 , "image/x-xpixmap"},
{"xwd" , 3 , "image/x-xwindowdump"},
{"xyz" , 3 , "chemical/x-pdb"},
{"zip" , 3 , "application/zip"},
};
const char * getContentType(const char * file_name)
{
char * p1 = (char *)file_name + strlen(file_name) - 1;
int i = 0;
for(;*p1 && *p1 != '.';i++)
p1--;
if(*p1)
{
p1++;
//将所有字母转为小写
for(char * tmp = p1;*tmp;tmp++)
*tmp = tolower(*tmp);
//开始判断类型
for(int j = 0;j < (sizeof(list)/sizeof(struct type_list));j++)
{
if(list[j].suffix_len != i)
continue;
if(strcmp(list[j].suffix,p1) == 0)
return list[j].mime_type;
}
}
return bin_type;
}
/*
获取请求头的函数
返回第一行长度
也有点欠缺
*/
int get_header(int sock,void * buf)
{
int j = 0;
char * pBuf = (char *)buf;
#ifdef USEOLD
if(recv(sock,buf,BUF_SIZE,0))
{
//获取第一行的长度
while(*(pBuf + j) != '\n' && j < BUF_SIZE)
j++;
if(j > 13)
{
if(*(pBuf + j - 1) == '\r')
*(pBuf + j -1) = 0;
else
*(pBuf + j) = 0;
}
else
{
j = 0;
}
} else
*pBuf = 0;
return j;
#else
while(recv(sock,pBuf,1,0) && j < BUF_SIZE)
{
if(*pBuf == '\r')
continue;
else if(*pBuf == '\n' && *(pBuf - 1) == '\n')
{
*pBuf = 0;
return j;
}
j++,pBuf++;
}
return 0;
#endif
}
void errorHandle(int sig,char * argv[])
{
switch(sig) {
case -2:
perror("Error");
break;
case -1:
break;
case 0:
printf("Option requires an argument\n");
break;
default:
printf("Invalid command arguments:\'%s\'\n",argv[sig]);
break;
}
exit(-1);
}
void do_request(int sock)
{
FILE * fp;
int j = 0;
char buf[BUF_SIZE] = {0};
printf("---------------------------------\n");
if(!(j = get_header(sock,&buf[0])))
{
error_msg:
printf("Bad request\n");
send_msg(sock,bad_request);
close(sock);
return;
}
printf("%s\n",buf);
int k = 1;
char * request[3];
request[0] = &buf[0];
//分离请求头
#ifdef USEOLD
for(int r = 0;k < 3;k++)
{
loop:
if(j > r)
{
if(buf[r] != ' ')
{
r++;
goto loop;
} else {
buf[r] = 0;
r++;
request[k] = &buf[r];
}
} else
break;
}
#else
for(int r = 0;k < 3 && j > r;k++)
{
loop:
r++;
if(buf[r] == ' ')
{
buf[r] = 0;
r++;
request[k] = &buf[r];
continue;
}
goto loop;
}
*(request[2] + 8) = 0;
#endif
//检查分离的请求头
if(k < 2)
goto error_msg;
printf("Method:%s\nURL:%s\n\n",request[0],request[1]);
//去掉请求网址的第一个斜杠
request[1]++;
if(strcmp("GET",request[0]) == 0)
{
printf("Succeed\n");
if(strcmp("HTTP/1.1",request[2]))
goto error_msg;
if(strcmp("?d",request[2] - 3) == 0)
{
*(request[2] - 3) = 0;
k = 0;
}
fp = fopen(request[1],"rb");
if(fp == NULL)
{
send_msg(sock,not_found);
close(sock);
return;
}
printf("Send header\n");
/*
这一部分是专门用于分析文件类型的
*/
send_msg(sock,header);
if(k)
{
request[2] = (char *)getContentType(request[1]);
send(sock,request[2],strlen(request[2]),0);
} else
send(sock,bin_type,24,0);
send_msg(sock,"\r\n\r\n");
rewind(fp);
printf("Send file '%s'\n",request[1]);
//这里用来发送文件
for(int flen;(flen = fread(buf,1,BUF_SIZE,fp)) > 0;)
send(sock,buf,flen,0);
fclose(fp);
close(sock);
return;
}
printf("Method not supported\n");
send_msg(sock,method_not_supported);
close(sock);
return;
}
int main(int argc,char * argv[])
{
struct sockaddr_in server_addr,client_addr;
fd_t server_fd,client_fd;
int port = 0;
//处理参数
for(int i = 1;i < argc;i++)
{
if(strcmp("--port",argv[i]) == 0)
{
i++;
if(i < argc)
port = atoi(argv[i]);
else
errorHandle(0,argv);
continue;
}
errorHandle(i,argv);
}
//检查端口是否不为零
if(!port)
{
printf("You don't set port\n");
printf("Determine port as 8080\n");
port = 8080;
}
if((server_fd = socket(AF_INET,SOCK_STREAM,0)) == 0)
errorHandle(-2,NULL);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(port);
if(bind(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
errorHandle(-2,NULL);
printf("Bind completed.\n");
if(listen(server_fd,20) < 0)
errorHandle(-2,NULL);
unsigned int addr_sz = sizeof(client_addr);
while(1)
{
printf("Waiting for connection...\n");
//如果接受客户端失败
//则关闭客户端套接字
if((client_fd = accept(server_fd,(struct sockaddr *)&client_addr,&addr_sz)) < 0)
{
printf("Failed when accept.\n");
printf("Close the connection.\n");
close(client_fd);
continue;
}
printf("Connected.\n");
do_request(client_fd);
}
return 0;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/smithgoll/c-language-learning.git
git@gitee.com:smithgoll/c-language-learning.git
smithgoll
c-language-learning
c语言学习
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891