C语言实现的Web服务器(转-kungstriving)
该程序通过标准socket实现简单Http服务器
运行该服务器可以通过浏览器访问服务器目录下的
Html文件和jpg图片 完成初步的Http服务器功能
***************************************************/
#include <sys/stat.h>
#include <iostream>
using namespace std;
#define HOSTLEN 256 //主机名长度
#define BACKLOG 10 //同时等待的连接个数
该方法包装了send()
通过该方法发送数据 能够全部发出
没有遗漏
**************************************/
int sendall(int s, char *buf, int *len) {
int total = 0; // 已经发送字节数
int bytesleft = *len; //还剩余多少字节
int n;
while(total < *len) {
n = send(s, buf+total, bytesleft, 0);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // 返回实际发送出去的字节数
return n==-1?-1:0; // 成功发送返回0 失败-1
}
该方法处理错误请求
并向客户端发送错误信息
**************************************/
void wrong_req(int sock) {
char* error_head = "HTTP/1.0 501 Not Implemented\r\n"; //输出501错误
int len = strlen(error_head);
if (sendall(sock, error_head, &len) == -1) { //向客户发送
printf("Sending failed!");
return;
}
len = strlen(error_type);
if (sendall(sock, error_type, &len) == -1) {
printf("Sending failed!");
return;
}
len = strlen(error_end);
if (sendall(sock, error_end, &len) == -1) {
printf("Sending failed!");
return;
}
len = strlen(prompt_info);
if (sendall(sock, prompt_info, &len) == -1) {
printf("Sending failed!");
return;
}
}
该方法判断用户请求的文件是否存在
不存在返回true 存在返回false
***********************************/
bool not_exit(char* arguments) {
struct stat dir_info;
return (stat(arguments, &dir_info) == -1);
}
所请求的文件不存在
*************************************/
void file_not_found(char* arguments, int sock) {
int len = strlen(error_head);
if (sendall(sock, error_head, &len) == -1) { //向客户端发送
printf("Sending error!");
return;
}
len = strlen(error_type);
if (sendall(sock, error_type, &len) == -1) {
printf("Sending error!");
return;
}
len = strlen(error_end);
if (sendall(sock, error_end, &len) == -1) {
printf("Sending error!");
return;
}
strcat(prompt_info, arguments);
len = strlen(prompt_info);
if (sendall(sock, prompt_info, &len) == -1) { //输出未找到的文件
printf("Sending error!");
return;
}
}
发送Http协议头部信息
其中包括响应类型和Content Type
*************************************/
void send_header(int send_to, char* content_type) {
char* head = "HTTP/1.0 200 OK\r\n"; //正确的头部信息
int len = strlen(head);
if (sendall(send_to, head, &len) == -1) { //向连接的客户端发送数据
printf("Sending error");
return;
}
char temp_1[30] = "Content-type: "; //准备好要连接的字串
strcat(temp_1, content_type); //构造content_type
strcat(temp_1, "\r\n");
len = strlen(temp_1);
if (sendall(send_to, temp_1, &len) == -1) {
printf("Sending error!");
return;
}
}
}
取得用户所请求的文件类型
即文件后缀 (.html .jpg .gif)
************************************/
char* file_type(char* arg) {
char * temp; //临时字符串指针
if ((temp=strrchr(arg,'.')) != NULL) { //取得后缀
return temp+1;
}
return ""; //如果请求的文件名中没有. 则返回空串
}
该方法为程序核心
负责真正发送文件 如*.html *.jpg等
*************************************/
void send_file(char* arguments, int sock) {
char* content_type = "text/plain"; //初始化type='text/plain'
FILE* read_from; //本地文件指针 从该文件中读取.html .jpg等
int readed = -1; //每次读得的字节数
if (strcmp(extension, "html") == 0) { //发送内容为html
content_type = "text/html";
}
content_type = "image/gif";
}
content_type = "image/jpg";
}
if(read_from != NULL) { //指针不为空
char read_buf[128]; //读文件时的字节缓存数组
send_header(sock, content_type); //发送协议头
send(sock, "\r\n", 2, 0); //再加一个"\r\n" 不能缺少 格式要求
fgets(read_buf, 128, read_from); //读取
int len = strlen(read_buf);
if (sendall(sock, read_buf, &len) == -1) { //发送数据
printf("Sending error!"); //出现发送错误 显示到控制台 继续发送
continue;
}
}
}
}
解析并处理用户请求
***********************************/
void handle_req(char* request, int client_sock) {
char arguments[BUFSIZ]; //保存解析到的请求的文件
* 在用户请求前加上当前目录符号
*/
strcpy(arguments, "./"); //注意该符号在不同操作系统的区别
* 解析请求
*/
if (sscanf(request, "%s%s", command, arguments+2) != 2) {
return; //解析出错在返回
}
printf("handle_cmd: %s\n",command); //向控制台输出此时的命令
printf("handle_path: %s\n",arguments); //向控制台输出此时的请求路径
if (strcmp(command, "GET") != 0) { //请求命令格式是否正确
wrong_req(client_sock);
return;
}
file_not_found(arguments, client_sock);
return;
}
return;
}
该方法构造服务器端的SOCKET
返回构造好的socket描述符
*************************************/
int make_server_socket() {
struct sockaddr_in server_addr; //服务器地址结构体
if (tempSockId == -1) { //如果返回值为-1 则出错
return -1;
}
* 填充服务器连接信息
*/
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //本地地址
memset(&(server_addr.sin_zero), '\0', 8);
sizeof(server_addr)) == -1) { //绑定服务 如果出错 则返回-1
printf("bind error!\n");
return -1;
}
printf("listen error!\n");
return -1;
}
}
主函数main()
程序入口
***********************/
void main(int argc, char * argv[]) {
* 调用WSAStartup() 便于访问sockets library
*/
WSADATA wsaData;
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
int acc_socket; //接收到的用户连接的socket
int sock_size = sizeof(struct sockaddr_in);
printf("Server exception!\n");
exit(2);
}
* 主循环
*/
while(true) {
acc_socket = accept(server_socket, (struct sockaddr *)&user_socket, &sock_size); //接收连接
//cout << inet_ntoa(user_socket.sin_addr) << endl; //测试用:-)//
/*
* 读取客户请求
*/
int numbytes;
char buf[100];
if ((numbytes=recv(acc_socket, buf, 99, 0)) == -1) {
perror("recv");
exit(1);
}
//printf("buf ... %s", buf); //测试用
* 处理用户请求
*/
handle_req(buf, acc_socket);
}
}
C语言实现的Web服务器(转-kungstriving)的更多相关文章
- C语言构建小型Web服务器
#include <stdio.h> #include <sys/socket.h> #include <stdlib.h> #include <string ...
- 第37章 socket编程 之练习:实现简单的web服务器
一.参考网址 1.linux C学习之实现简单的web服务器 2.C语言实现简单Web服务器(一)
- Web服务器和动态语言如何交互--CGI&FastCGI&FPM浅谈
一个用户的Request是如何经过Web服务器(Apache,Nginx,IIS,Light)与后端的动态语言(如PHP等)进行交互并将结果返回给用户的呢? 本文浅谈个人观点,可能有误,欢迎拍砖,共同 ...
- 基于windows IIS的C语言CGI WEB服务器环境搭建
网页编程对我来说特别亲切,因为我就是从html.ASP.PHP一步步接触编程的.自己的编程爱好也是从那里一点一点被满足.不过离开大学之后很久没有碰过WEB了,最近看到嵌入式中的涉及到的web服务器,了 ...
- web服务器和后端语言的关系
1.web服务nginx和php的相互关系 : https://www.cnblogs.com/luckylihuizhou/p/6387171.html 个人理解:web服务器本身没有处理后端语言 ...
- C/C++编程日记:用C语言实现的简单Web服务器(Linux),全代码分享!
相信大家对Apache都有所听闻,Apache是目前使用最为广泛我Web服务器.大家可以从news.netcraft.com/这个网站得到证实. 这是腾讯的uptime.netcraft.com/up ...
- 闲来无聊,研究一下Web服务器 的源程序
web服务器是如何工作的 1989年的夏天,蒂姆.博纳斯-李开发了世界上第一个web服务器和web客户机.这个浏览器程序是一个简单的电话号码查询软件.最初的web服务器程序就是一个利用浏览器和web服 ...
- Raspkate - 基于.NET的可运行于树莓派的轻量型Web服务器
最近在业余时间玩玩树莓派,刚开始的时候在树莓派里写一些基于wiringPi库的C语言程序来控制树莓派的GPIO引脚,从而控制LED发光二极管的闪烁,后来觉得,是不是可以使用HTML5+jQuery等流 ...
- 一个简单的 Web 服务器 [未完成]
最近学习C++,linux和网络编程,想做个小(mini)项目. 就去搜索引擎, 开源中国, Sourceforge上找http server的项目. 好吧,也去了知乎. 知乎上程序员氛围好, ...
随机推荐
- html5 drag and drop
注:链接.图片默认是draggable的. mousemove在整个拖放的过程中不会被触发. dragStart设置: e.dataTransfer.effectAllowed = "mov ...
- python decorator的理解
一.decorator的作用 装饰器本质上是一个Python函数,可以让其他函数在不做任何代码变动的前提下增加额外功能. 装饰器的返回值也是一个函数对象.python里函数也是对象. 它经常用于有切面 ...
- iOS开发 百度坐标点的计算
BMKMapPoint point1 = BMKMapPointForCoordinate(_userGps); BMKMapPoint point2 = BMKMapPointForCoordina ...
- [ubuntu14.04 amd64 ]搜狗拼音輸入法安裝
这个网址下载之后,双击下载的deb文件http://mirrors.sohu.com/deepin/pool/non-free/f/fcitx-sogoupinyin-release/ 就会在ubun ...
- 当 IDENTITY_INSERT 设置为 OFF 时,不能为表‘XXX’中的标识列插入显式值。
在创建事务复制时,很多时候不一定使用快照进行初始化,而是使用备份还原初始化.当对有标识列(即identity的自增列)的表进行复制的时候,使用备份还原初始化搭建起来的复制常常就会报错,即:当 IDEN ...
- html5-表单
例子: text,number,email 的输入框 <!-- required:必填项 --> <!-- autofocus:获得焦点 --> <!-- placeho ...
- linux 下mysql的安装,并设置必要的密码
首先,我使用的是redhat linux ,版本号为: [root@localhost init.d]# cat /proc/version Linux version - (bhcompile@po ...
- ShopNc基本介绍
ShopNc学习笔记: 1.shopNc每个文件夹定义了单入口文件eg:shopnc/admin/index.php, shopnc/cms/index.php 2.MVC M: $model = M ...
- HDU 1106 排序 题解
排序 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...
- WP8.1 Study17:网络之后台下载/上传及HttpClient
一.后台下载/上传 1.简介 使用BackgroundTransferGroup可以十分方便操作上传及下载文件,BackgroundDownloader和BackgroundUploader类中的方法 ...