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的项目. 好吧,也去了知乎. 知乎上程序员氛围好, ...
随机推荐
- iOS Question
Q1: dyld: Library not loaded: @rpath/libswiftCore.dylib 1. 退出 Xcode2. 重启电脑3. 找到 这个 DerivedData 文件夹 删 ...
- python 中的[::-1]
for value in rang(10)涉及的数字倒序输出: for value in rang(10)[::-1]涉及的数字倒序输出: 一.反转 二.详解 这个是python的slice nota ...
- (转) C++中基类和派生类之间的同名函数的重载问题
下面有关派生类与基类中存在同名函数 fn: class A { public: void fn() {} void fn(int a) {} }; class B : public A { publi ...
- Web1.0、Web2.0、Web3.0的主要区别
Web1.0:以静态.单向阅读为主,网站内信息可以直接和其他网站信息进行交互,能通过第三方信息平台同时对多家网站信息进行整合使用. Web2.0:以分享为特征的实时网络,用户在互联网上拥有自己的数据, ...
- Spring IoC原理详解
去掌握一门技术的时候,往往很多人都忽略了一点,只是一味地去写代码,原理层面的东西从来就不理会 还有就是学习的过程中,不去想为什么有了当前的写法,却有着这么一门技术可以代替它 一般来说,在写程序的时候, ...
- 解决Linux下Tomcat日志目录下的catalina.log日志文件过大的问题
本文摘自:(http://blog.csdn.net/stevencn76/article/details/6246162) 分类: Java技术专区2011-03-13 12:25 5017人阅读 ...
- iOS开发多线程篇—NSOperation基本操作
iOS开发多线程篇—NSOperation基本操作 一.并发数 (1)并发数:同时执⾏行的任务数.比如,同时开3个线程执行3个任务,并发数就是3 (2)最大并发数:同一时间最多只能执行的任务的个数. ...
- Regsvr32.exe 用法
RegSvr32.exe 具有以下命令行选项: Regsvr32 [/u] [/n] [/i[:cmdline]] dllname /u - 取消注册服务器 /i - 调用 DllInstall,为 ...
- ubuntu 14.04 下找不到命令,路径出错
在安装一些东西时,可能操作上不小心把路径覆盖或打错,造成一些基本命令如ls mkdir等无法使用,就会出现以下提示错误. 错误: 由于/usr/bin 不在PATH 环境变量中,故无法找到该命令 根本 ...
- Linux shell的&&和||
Linux shell的&&和|| shell 在执行某个命令的时候,会返回一个返回值,该返回值保存在 shell 变量 $? 中.当 $? == 0 时,表示执行成功:当 $? ...