用C编写一个简单的、基本的http服务器
2014-09-20 01:33
225 查看
翻到一份去年自己实现的http服务器,编译环境为VC6.0,用纯C编写,本来想完善以后才发出来的,结果拖延症发作......
ps:代码仅供学习
工程下载:http://download.csdn.net/detail/wailovet/7945827
main.h
________________________
main.c
________________________________________________
config
————————————————————
ps:代码仅供学习
工程下载:http://download.csdn.net/detail/wailovet/7945827
main.h
________________________
#include <stdio.h> #include <string.h> #include <stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include <winsock2.h> #include <windows.h> //包含文件 #pragma comment(lib, "ws2_32.lib") //静态编译 #define CONFIG_FILE "./config" #define MAXDATA 512 typedef struct { char url[256]; char dir[256]; char host[256]; char accept[256]; char accept_language[64]; char content_type[64]; char cookie[256]; } RequestHeaders ; struct { char root_path[256]; char default_file[64]; int server_port; } Config ; DWORD WINAPI Thread(LPVOID lpParam);//等待连接进程 //功能 将接收到的http头信息解析到结构RequestHeaders //参数 RequestHeaders为接受http请求头信息,str为字符串形式的头信息,socket为当前连接客户字符串 //返回值 0为正常,1为出现异常 int strToRequestHeaders(RequestHeaders *rh,char *str,int socket); //功能 根据http请求信息发送指定文件 //参数 socket为当前连接客户字符串,RequestHeaders为接受http请求头信息 //返回值 0为正常发送,-1为文件打开失败 int sendFile(int socket,RequestHeaders rh); //功能 加载http服务器配置 void loadConfig(); //功能 服务端http头信息的串接 //参数 RequestHeaders为接受http请求头信息 //返回值 服务端http头信息字符串形式 char* makeHeadPack(RequestHeaders rh); char* readLoad(char *allConfig,char *name); //功能 查询文件大小 //参数 fp为路径字符串 //返回值 文件大小,单位为字节 long getFileSize(char* fp); //功能 当前连接的用户跳转到指定连接 //参数 socket为当前连接客户字符串 //返回值 为0 int moveUrl(int socket,char *url); //功能 判断路径是否为文件夹 //参数 fp为路径字符串 //返回值 1为参数所指定路径为文件夹 0为普通文件 int isFolder(char* fp);
main.c
________________________________________________
#include "main.h" struct sockaddr_in my_socket_info;//服务端配置 int my_first_socket,tmp_socket; int backlog = 5; int pnum = 0; //线程数 int main(){ WSADATA WSAData={0}; WSAStartup(MAKEWORD(2,2), &WSAData); loadConfig(); my_socket_info.sin_family = PF_INET; my_socket_info.sin_port = htons(Config.server_port); my_socket_info.sin_addr.s_addr = htonl(INADDR_ANY); my_first_socket = socket(PF_INET, SOCK_STREAM, 0); bind(my_first_socket,(struct sockaddr *)&my_socket_info,sizeof(my_socket_info)); listen(my_first_socket,backlog); while(1){ tmp_socket = accept(my_first_socket,(struct sockaddr *)&my_socket_info,NULL); CreateThread(NULL,0,Thread,NULL,0,NULL); //printf("starts"); Sleep(50); } return 0; } DWORD WINAPI Thread( LPVOID lpParam ) { char head_buf[2*MAXDATA]=""; char buf[MAXDATA+1]="";//数据缓冲区 int my_sec_socket; RequestHeaders head_info; int i = 0,q=0; my_sec_socket = tmp_socket; pnum++; //接收http头信息 while((i = recv(my_sec_socket,buf,MAXDATA,0))){ buf[i] = '\0'; strcat(head_buf,buf); q=q+i; if(i<MAXDATA){ break ; } } // 解析头信息 if(strToRequestHeaders(&head_info,head_buf,my_sec_socket)==1){ closesocket(my_sec_socket); return 0; } strcpy(head_buf,makeHeadPack(head_info)); send(my_sec_socket,head_buf, strlen(head_buf), 0); sendFile(my_sec_socket,head_info); pnum--; closesocket(my_sec_socket); return 0; } int strToRequestHeaders(RequestHeaders *rh,char *str,int socket) { char tmp[2048]; char *s; strcpy(tmp,str); s = strstr(strupr(tmp) ,"GET ")+4; if(!(s-4)){ return 1; } strstr(s," ")[0]='\0'; strcpy(rh->dir,Config.root_path); strcat(rh->dir,s); if(rh->dir[strlen(rh->dir)-1]=='/'){ strcat(rh->dir,Config.default_file); } if(isFolder(rh->dir)){ strcat(s,"/"); moveUrl(socket,s); return 1; } if(strrchr(rh->dir,'.')){ strcpy(rh->content_type,strrchr(rh->dir,'.')); } return 0; } int sendFile(int socket,RequestHeaders rh) { unsigned char buf[MAXDATA]; char *error = ""; int i=MAXDATA,sum=0; FILE * fp = fopen(rh.dir,"rb"); if(NULL == fp){ send(socket,"404", 3, 0); return -1; //打开错误 } while( (i = fread(buf,sizeof(unsigned char), MAXDATA,fp)) != 0 ){ send(socket,buf,i, 0); } fclose(fp); return 0; } /* bug未解决 int sendFile(int socket,RequestHeaders rh) { unsigned char buf[MAXDATA]; char *error = ""; int i=MAXDATA,sum=0; int fp = open(rh.dir,O_RDONLY); printf("%s",rh.dir); if(!fp){ send(socket,"404", 3, 0); return -1; //打开错误 } while( !eof(fp) ){ i = read(fp,buf,MAXDATA); send(socket,buf,i, 0); } close(fp); return 0; }*/ char* makeHeadPack(RequestHeaders rh) { char header_buf[256]="HTTP/1.1 200 OK\r\n"; char str_file_size[25]; if(strstr(rh.content_type,"html")){ strcat(header_buf,"Content-Type: text/html;\r\n"); } itoa(getFileSize(rh.dir), str_file_size, 10); strcat(header_buf,"Content-Length:"); strcat(header_buf,str_file_size); strcat(header_buf,"\r\nServer: tinyHttpServer\r\nConnection: close\r\n\r\n"); return header_buf; } long getFileSize(char* fp) { struct stat f_stat; if(isFolder(fp)){ return -1; } stat(fp, &f_stat); return f_stat.st_size; } char *readLoad(char *allConfig,char *name){ char line[256],*tmp; int i,k; tmp = strstr(allConfig,name); k=0; if(!tmp){ return ""; } //这里需要删除空格字符 for(i=0;tmp[k]!='\0'&&tmp[k]!='\n';k++){ if(tmp[k]!=' '&&tmp[k]!='\n'&&tmp[k]!=13){ line[i]=tmp[k]; i++; } } line[i]='\0'; strcpy(line,strstr(line,":")+1); return line; } void loadConfig() { char ch[2]; char *line; char *conf; int i; FILE * fp = fopen(CONFIG_FILE,"rb"); if(!fp){ printf("error"); return ; } ch[1] = '\0'; conf = malloc(sizeof(char)*getFileSize(CONFIG_FILE)+4); conf[0]= '\0'; while((ch[0]=fgetc(fp))!=EOF){ strcat(conf,ch) ; } strcpy(Config.root_path,readLoad(conf,"root_path")); Config.server_port = atoi(readLoad(conf,"port")); strcpy(Config.default_file,readLoad(conf,"default_page")); printf(" %s \n %d",Config.default_file,Config.server_port); } int moveUrl(int socket,char *url) { char head[512]; strcpy(head,"HTTP/1.1 302 Found\r\nServer: tinyHttpServer\r\nLocation:"); strcat(head,url); strcat(head,"\r\n\r\n"); send(socket,head, strlen(head), 0); return 0; } int isFolder(char* fp) { char* root_dir = _getcwd(NULL,NULL); if(_chdir(fp)==0){ _chdir(root_dir); return 1; } _chdir(root_dir); return 0; }
config
————————————————————
root_path : ./www port : 51000 default_page:index.html
相关文章推荐
- 通过编写一个简单的漏洞扫描程序学习Python基本语句
- 编写、编译、安装、移除一个内核模块的基本过程,不能再简单了的
- c#编写一个简单的http服务器
- 用Python实现简单的HTTP服务器(2)--实现一个基本功能的HTTP服务器
- 利用C#编写一个简单的抓网页应用程序
- 利用C#编写一个简单的抓网页应用程序
- [基本算法]Java——编写一个线段类,实现基本数学算法
- 利用C#编写一个简单的抓网页应用程序
- 【Rebol 学习笔记】第一篇:编写一个简单的 CGI 程序
- 一个用php3编写的简单计数器
- 利用 Debug API 编写一个简单的脱壳机
- C#编写的一个简单的登陆界面对话框的原代码
- Win32汇编教程四 编写一个简单的窗口
- 一个用php3编写的简单计数器
- 使用NCindy编写一个Http服务器
- 一步一步SharePoint 2007之二十五:编写一个最简单的WebPart(3)——添加WebPart
- Linux下,使用C/C++编写一个简单的消息处理程序
- 一个简单木马程序的编写
- ASP编写的一个简单的颜色吸取器
- 利用C#编写一个简单的抓网页应用程序