C++实现一个web服务器, 弱智版服务器
监听本地的8888端口, 当在浏览器中访问这个地址的时候, 返回一堆HTML数据, 这种方式返回的数据不稳定,不同浏览器解析不同, 因为我们没有定义返回文件类型:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h> int main() {
int sock = socket(AF_INET, SOCK_STREAM, );
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons();
address.sin_addr.s_addr = inet_addr("192.168.0.58");
int ret = bind(sock , (const struct sockaddr*)&address , sizeof(address));
ret = listen(sock, );
printf("lisening..\n"); struct sockaddr_in client_address;
socklen_t len;
int newsock = accept(sock, (struct sockaddr*)&client_address, &len);
printf("client conneting\n");
FILE *fp = fopen("./html/index.html","rb");
char buf[] = {};
fread(buf, , , fp);
printf("content is %s\n", buf);
send(newsock, buf, strlen(buf), );
close(newsock);
close(sock);
return ;
}
给服务器的返回设置文件类型和文件大小信息, 避免页面出现乱码和页面的正常解析:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h> int main() {
int sock = socket(AF_INET, SOCK_STREAM, );
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons();
address.sin_addr.s_addr = inet_addr("192.168.1.102");
int ret = bind(sock , (const struct sockaddr*)&address , sizeof(address));
ret = listen(sock, );
printf("lisening..\n"); struct sockaddr_in client_address;
socklen_t len;
int newsock = accept(sock, (struct sockaddr*)&client_address, &len);
printf("client conneting\n"); //char recvData[1024] ={0};
//recv(newsock, recvData, sizeof(recvData), 0);
//printf("receive data:%s", recvData);
FILE *fp = fopen("./html/index.html","rb"); if( fp == NULL ){
printf("failed to open img\n");
}
fseek(fp, , SEEK_END);
long fileLen = ftell(fp);
fseek(fp, , SEEK_SET); char buf[] = {};
strcat(buf, "HTTP/1.0 200 OK\r\n");
strcat(buf, "Content-Type: text/html;charset=UTF-8\r\n"); char contentLength[] = {};
sprintf(contentLength, "Content-Length: %ld\r\n\r\n", fileLen);
strcat(buf, contentLength); fread(buf+strlen(buf), , , fp);
send(newsock, buf, strlen(buf), );
close(newsock);
close(sock);
return ;
}
打开本地的PNG图片,并返回给客户端浏览器, 和上面的代码还有一点区别就是, 服务器有返回Content-type和Content-Length :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h> int main() {
int sock = socket(AF_INET, SOCK_STREAM, );
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons();
address.sin_addr.s_addr = inet_addr("192.168.1.102");
int ret = bind(sock , (const struct sockaddr*)&address , sizeof(address));
ret = listen(sock, );
printf("lisening..\n"); struct sockaddr_in client_address;
socklen_t len;
int newsock = accept(sock, (struct sockaddr*)&client_address, &len);
printf("client conneting\n");
FILE *fp = fopen("./imgs/img.png","rb");
if( fp == NULL ){
printf("failed to open img\n");
}
fseek(fp, , SEEK_END);
long fileLen = ftell(fp);
fseek(fp, , SEEK_SET); char buf[] = {};
strcat(buf, "HTTP/1.0 200 OK\r\n");
strcat(buf, "Content-Type: image\png;charset=UTF-8\r\n"); char contentLength[] = {};
sprintf(contentLength, "Content-Length: %ld\r\n\r\n", fileLen);
strcat(buf, contentLength); //strlen just string length; but sizeof return all the size;
fread(buf+strlen(buf), , , fp);
send(newsock, buf, , ); close(newsock);
close(sock);
return ;
}
搭建一个服务器:
/*****************************************************************
system:kali enviroment:g++ compile command:gcc webServer.c -g -o webServer -lpthread *****************************************************************/ #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #include <netinet/in.h> #include <unistd.h> #include <pthread.h> #include <stdio.h> #include <string.h> #include <arpa/inet.h> #define PORT 8848 #define BACKLOG 5 #define MAXDATASIZE 1000 #define DEBUG 1 void process_cli(int connectfd, sockaddr_in client); int sendobj(int connectfd,char* serverfilepath); int IsDIR(char* fpath); int fileordirExist(char* fpath); char* getextname(char*); void* getHead(char* extname); void* start_routine(void* arg); void msg404(int connectfd); struct ARG { int connfd; sockaddr_in client; }; main() { int listenfd, connectfd; pthread_t thread; //id of thread ARG *arg; //pass this var to the thread struct sockaddr_in server; //server's address info struct sockaddr_in client; //client's int sin_size; //create tcp socket #ifdef DEBUG printf("socket.... "); #endif if ((listenfd = socket(AF_INET, SOCK_STREAM, )) == -) { perror("creating socket failed."); exit(); } int opt = SO_REUSEADDR; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); bzero(&server,sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(PORT); server.sin_addr.s_addr = htonl(INADDR_ANY); printf("bind.... "); if(bind(listenfd,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -) { perror("bind error."); exit(); } printf("listen.... "); if(listen(listenfd,BACKLOG) == -) { perror("listen() error "); exit(); } sin_size = sizeof(struct sockaddr_in); while() { //accept() using main thread printf("accepting.... "); if((connectfd = accept(listenfd, (struct sockaddr *)&client, (socklen_t*)&sin_size)) == -) { printf("accept() error "); } arg = new ARG; arg->connfd = connectfd; memcpy((void *)&arg->client, &client, sizeof(client)); //invoke start_routine to handle this thread #ifdef DEBUG printf("thread_creating...."); #endif if(pthread_create(&thread, NULL, start_routine, (void*)arg)){ perror("pthread_create() error"); exit(); } } close(listenfd); } //handle the request of the client void process_cli(int connectfd, sockaddr_in client) { int num; //char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE]; char requestline[MAXDATASIZE], filepath[MAXDATASIZE], cmd[MAXDATASIZE],extname[MAXDATASIZE]; int c; FILE *fp; FILE *cfp; fp = fdopen(connectfd,"r"); #ifdef DEBUG printf("the host is:%s ",inet_ntoa(client.sin_addr) ); #endif fgets(requestline,MAXDATASIZE,fp); #ifdef DEBUG printf(" THE REQUEST IS :%s ",requestline); #endif strcpy(filepath,"./"); sscanf(requestline,"%s%s",cmd,filepath+); strcpy(extname, getextname(filepath)); #ifdef DEBUG printf("cmd:%s filepath:%s extname:%s ",cmd,filepath,extname); printf("string comparing :::::::::::::start::::::::::::::: "); #endif if(strcmp(cmd,"GET") == ){ //the command is get #ifdef DEBUG printf("cmd(%s)==GET \n",cmd); #endif //is this a file or dir or notexist?
printf("filepath is .... : %s\n", filepath);
if(fileordirExist(filepath)){ //is a file or dir or none //is this a dir if(IsDIR(filepath)){ //is a dir #ifdef DEBUG printf("%s is a DIR ",filepath); #endif if( fileordirExist( strcat(filepath,"index.htm") )){ sendobj(connectfd,"index.htm"); }else if(fileordirExist(strcat(filepath,"index.html"))){ sendobj(connectfd,"index.htm"); }else{ msg404(connectfd); } }else{ //is a file #ifdef DEBUG printf("%s is a file\n",filepath); #endif sendobj(connectfd, filepath); } }else{ #ifdef DEBUG printf("404 "); #endif msg404(connectfd); } }else{ #ifdef DEBUG printf("cmd(%s)!=GET \n",cmd); #endif } #ifdef DEBUG printf(":::::::::::::end::::::::::::::: \n"); #endif close(connectfd); } //send the 404 error message to the client void msg404(int connectfd) { char* msg; msg = "HTTP/1.0 404 Not Found Content-Type: text/plain 404 not found by Manio"; send(connectfd,msg,strlen(msg),); } //is the filepath a file or directory int fileordirExist(char* fpath) { struct stat filestat; return ( stat(fpath,&filestat) != -); } // is the filepath a directory int IsDIR(char* fpath) { #ifdef DEBUG printf("IN IsDIR "); #endif struct stat filestat; return ( stat(fpath,&filestat) != - && S_ISDIR(filestat.st_mode)); } //send the data of the file which the client want int sendobj(int connectfd,char* serverfilepath) { FILE* fp,*cfp;
char buf[] = {}; int c; fp = fopen(serverfilepath,"rb"); printf("filepath is %s \n ", serverfilepath); if( fp == NULL ){
printf("failed to open html file\n");
}
fseek(fp, , SEEK_END);
long fileLen = ftell(fp);
fseek(fp, , SEEK_SET); strcat(buf, "HTTP/1.0 200 OK\r\n");
strcat(buf, "Content-Type: ");
char* fileExt = getextname(serverfilepath);
strcat(buf, (char *)getHead(fileExt));
strcat(buf, ";charset=UTF-8\r\n"); char contentLength[] = {};
sprintf(contentLength, "Content-Length: %ld\r\n\r\n", fileLen);
strcat(buf, contentLength); fread(buf+strlen(buf), , , fp);
printf("buf is %s\n", buf);
send(connectfd, buf, strlen(buf), ); return ; } //write the packet header to the client void* getHead(char* extname) { #ifdef DEBUG printf("INGETHEAD:::::::extname is %s::::::: \n",extname); #endif char* content = "text/plain"; if( strcmp(extname,"html") == || strcmp(extname,"htm") == ) content = "text/html"; else if ( strcmp(extname,"css") == ) content = "text/css"; else if ( strcmp(extname,"gif") == ) content = "image/gif"; else if ( strcmp(extname,"jpeg") == || strcmp(extname,"jpg") == ) content = "image/jpeg"; else if ( strcmp(extname,"png") == ) content = "image/png"; return (void *)content; } //get the extent name of the file char* getextname(char* filepath) { char* p; if(( p = strrchr(filepath,'.')) != NULL) return p+; return NULL; } //invoked by pthread_create void* start_routine(void* arg) { ARG *info; info = (ARG *)arg; process_cli(info->connfd, info->client); delete arg; pthread_exit(NULL); }
C语言的限制很少..类型可以随便转..系统相对于把所有的权利交给我们了, 所以C语言容易出问题
C++搭建一个web服务器:http://www.cppblog.com/cuijixin/archive/2008/07/02/55112.html
C++实现一个web服务器, 弱智版服务器的更多相关文章
- 部署Eclipse中的Web项目到Tomcat服务器运行
用Eclipse开发Web项目时,可以通过Tomcat服务器运行Web项目,此时Web项目被部署在[WorkSpace]\.metadata\.plugins\org.eclipse.wst.serv ...
- 手写一个Web服务器,极简版Tomcat
网络传输是通过遵守HTTP协议的数据格式来传输的. HTTP协议是由标准化组织W3C(World Wide Web Consortium,万维网联盟)和IETF(Internet Engineerin ...
- 【重点突破】——使用Express创建一个web服务器
一.引言 在自学node.js的过程中有一个非常重要的框架,那就是Express.它是一个基于NodeJs http模块而编写的高层模块,弥补http模块的繁琐和不方便,能够快速开发http服务器.这 ...
- python web编程 创建一个web服务器
这里就介绍几个底层的用于创建web服务器的模块,其中最为主要的就是BaseHTTPServer,很多框架和web服务器就是在他们的基础上创建的 基础知识 要建立一个Web 服务,一个基本的服务器和一个 ...
- 建立一个node.js服务器(使用express搭建第一个Web环境)
一.官网下载node.js 下载地址:https://nodejs.org/en/download/ 根据向导,下一步安装就可以了! 二.使用express搭建Web环境 express是一个开源的n ...
- 用java写一个web服务器
一.超文本传输协议 Web服务器和浏览器通过HTTP协议在Internet上发送和接收消息.HTTP协议是一种请求-应答式的协议——客户端发送一个请求,服务器返回该请求的应答.HTTP协议使用可靠的T ...
- 树莓派变成一个Web服务器: nginx + php + sqlite
将树莓派变成一个Web服务器,通过访问网页,就可以控制树莓派,比如:查看摄像头\开灯等等. 一想到Linux Web服务器,我们首先想到的是,Apache + MySql + Php. 树莓派可以安装 ...
- 用C写一个web服务器(二) I/O多路复用之epoll
.container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...
- 用C写一个web服务器(四) CGI协议
* { margin: 0; padding: 0 } body { font: 13.34px helvetica, arial, freesans, clean, sans-serif; colo ...
随机推荐
- 在 DELPHI 中 procedure 型变量与 method 型变量的区别
Procedure型变量: 在DELPHI中,函数.过程的地址可以赋给一个特殊类型的变量,变量可用如下方式声明: var p : procedure(num:integer); //过程 或: var ...
- Spark RDD的fold和aggregate为什么是两个API?为什么不是一个foldLeft?
欢迎关注我的新博客地址:http://cuipengfei.me/blog/2014/10/31/spark-fold-aggregate-why-not-foldleft/ 大家都知道Scala标准 ...
- 利用/proc/pid/pagemap将虚拟地址转换为物理地址
内核文档: Documentation/vm/pagemap.txt pagemap is a new (as of 2.6.25) set of interfaces in the kernel t ...
- iPhone/iPad各种文件路径详解 帮助了解自己的iphone和ipad
以下内容皆为转载分享iPhone里重要的目录路径有哪几个? 1. /private/var/mobile 新刷完的机器,要在这个文件夹下建一个Documents的目录,很多程序都要用到. 2. /pr ...
- springboot redis多数据源设置
遇到这样一个需求:运营人员在发布内容的时候可以选择性的发布到测试库.开发库和线上库. 项目使用的是spring boot集成redis,实现如下: 1. 引入依赖 <dependency> ...
- 波吉亚家族第一季/全集The Borgias 1迅雷下载
波吉亚家族 第一季 The Borgias Season 1 (2011)本季看点:<波吉亚家族>是一个非常复杂的故事,是现代人描绘这个臭名昭著的王朝家族过往历史的一副有趣又坦率的肖像画. ...
- IOS应用提交所需的ICON
如果提交的ipa包中,未包含必要的Icon就会收到类似的通知,为什么偏偏是Icon-76呢? 因为我们开发的游戏,默认是支持iphone以及ipad的,根据官方提供的参考 Icon-76.png是必须 ...
- sublime text的扩展插件
sublime text用作开发编辑器,还缺省二个比较重要功能:跨文件跳转.返回最后一次编辑的位置: 这里有二个插件正好解决此问题:CTags.ChangeList 其它常用的插件,google一 ...
- 制作高仿QQ的聊天系统(上)—— 布局文件 & 减少过度绘制
由于没有自己的服务器,我就找了个能实现双方通信的SDK,这个SDK是友盟的用户反馈SDK.本系列的博文关注的不是网络通信,而是如何在网络通信机制已经做好的情况下,做出一个可用的聊天系统.其实,刚开始做 ...
- JAVA垃圾回收机制概要
垃圾回收是JAVA中的一个大知识点,也是一个著名知识点,毕竟JAVA号称自己先进性的时候总是会带上垃圾回收.于是,它也成了面试中的常客,面试官动不动的就要你解释下什么是垃圾回收,以及它的原理是什么.当 ...