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的项目. 好吧,也去了知乎. 知乎上程序员氛围好, ...
随机推荐
- CSS布局基础之一设备像素,设备独立像素,设备像素比,css像素之间的关系
设备像素dp(device pixels) ppi(pixels per inch)表示每英寸所拥有的像素(pixel)数目,数值越高,代表屏幕能以更高的密度显示图像. 计算公式:ppi=像素数量/物 ...
- xml资源getStringArray(R.array.xxx)方法
在res/values/下新建menu_names.xml 代码如下: <?xml version="1.0" encoding="utf-8"?> ...
- 原生cookie
出于浏览器的安全性限制,从WEB应用程序中访问用户本地文件系统是有许多限制的.但是WEB站点的开发人员可以使用cookie,将少量信息保存在用户本地硬盘的指定空间中. document对象的cooki ...
- linux top命令
top命令参数 -h:help表示显示帮助的意思 -v:version显示版本的意思,和-h的功能一样 -u:user显示指定用户的进程,例如:top -u root -p:pid显示指定进程,例如: ...
- Logistic 分类器与 softmax分类器
首先说明啊:logistic分类器是以Bernoulli(伯努利) 分布为模型建模的,它可以用来分两种类别:而softmax分类器以多项式分布(Multinomial Distribution)为模型 ...
- Android BaseAdapter 数据和显示之间的Adapter 接口
http://www.cnblogs.com/mandroid/archive/2011/04/05/2005525.html
- Unix 初步(一)
1.Unix文件系统 Unix文件系统有三种文件类型:普通文件.目录文件和设备文件(将外部设备作为一种特殊的文件进行管理,实现输入输出统一而单纯的操作.) 2.Unix的网络功能 TCP/IP 3.r ...
- 关于DButils的简单介绍
android中的orm框架,一行代码就可以进行增删改查:支持事务,默认关闭:可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名)等等 ...
- node+mongodb+ionic+cordova
node + mongodb1,环境 windows 1,install nodejs 2,install npm | cd npmjs node cli.js install -gf1.1 2.no ...
- git 创建版本库
服务器安装后git后 1.在repositories仓库文件夹中执行git init aa.git --bare 创建aa的中心库(注意建立aa版本库时当前登录用户必须为git的相关用户,并保证/d ...