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的项目. 好吧,也去了知乎. 知乎上程序员氛围好, ...
随机推荐
- PHP文本框的值随下拉框改变
初学PHP,下面是实现文本框内容随下拉框变化的代码实现: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...
- Excle隐藏及展开列
当excle文档类目比较多的时候我们希望看第一列和某一列的对应关系可以选择隐藏中间列. 选中要隐藏的列,然后右键-->隐藏即可 需要展开的时候,选中:被隐藏列的前一列和后一列,然后当鼠标在列头( ...
- mysql5.x(<7) sql文件导入到5.7
一.修改sql—model http://www.linuxidc.com/Linux/2016-09/135372.htm
- Debian 上面五分钟搭建 WordPress - 博客/网站平台
没有废话,步骤如下: 下载安装软件,MySQL Apache PHP sudo aptitude install mysql-server mysql-client ##安装 MySQLsudo ap ...
- Mac下安装Node.js
今天介绍一下Mac下Node.js的下载安装方法,后面我们安装Bootstrap.Angurlar和jQuery等都是通过Node.js的npm方式的. 1.在必应中搜索“node.js mac”,第 ...
- C#完成最简单的WebService创建及使用
打开Visual Studio(我用的是2010)→文件→新建→项目→Visual C#→Web→ASP.NET Web 服务应用程序 打开Service1.asmx文件,会看到里面已经有个Hello ...
- 转AjaxControlToolkit的安装与使用详解
AjaxControlToolkit的安装与使用详解 AjaxControlToolkit下载http://ajax.asp.net/downloads/default.aspx?tabid=47ht ...
- 关于如何写UI及屏幕适配的一些技巧
因为公司开启了一个新的iOS项目, 所以近期比较忙, 没有更新博客,今天打算总结一下关于UI布局及屏幕适配的一些实战技巧,尤其使用纯代码,会对提升效率及代码易于维护等方面有明显帮助,这里提到的没有使用 ...
- cookie的使用
cookie的使用 1.创建cookie对象: function addCookie(name, value) { var path = filterRoot(); var cookieString ...
- 弄清UTF8和Unicode
长期以来,一直对字符串编码认识比较粗略,认为支持"特殊字符"编码就是Unicode.当然,.NET平台上很少需要考虑这类问题,但搞清一些基本概念还是很有好处的. Unicode这个 ...