`
kungstriving
  • 浏览: 131823 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

标准C实现WEB服务器

    博客分类:
  • Web
阅读更多
自己研究了好几天终于写出来一个,哈哈,当然也从网上得到了很多的帮助拉。谢谢大家咯!这个版本还不是很完善,但Web服务器的基本框架已经出来了,还有部分的功能需要进行进一步的测试和修改。虽然说C的开发比较慢,对于程序员来说比较难以操作,但通过用C写这些很底层的东西,可以更好的了解的象java的socket中的工作原理。有一定的帮助!
 
以下是源代码:
 
#include <winsock.h>
#include <sys/stat.h>
#include <iostream>
using namespace std;
#define SERVER_PORT 10000         //自定义的服务端口
#define HOSTLEN 256           //主机名长度
#define BACKLOG 10           //同时等待的连接个数

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;
 }
char* error_type = "Content-type: text/plain\r\n";  
 len = strlen(error_type);
 if (sendall(sock, error_type, &len) == -1) {
  printf("Sending failed!");
  return;
 }
char* error_end = "\r\n";
 len = strlen(error_end);
 if (sendall(sock, error_end, &len) == -1) {
  printf("Sending failed!");
  return;
 }
char* prompt_info = "The command is not yet completed\r\n";
 len = strlen(prompt_info);
 if (sendall(sock, prompt_info, &len) == -1) {
  printf("Sending failed!");
  return;
 }
}

bool not_exit(char* arguments) {
 struct stat dir_info;
 return (stat(arguments, &dir_info) == -1);
}

void file_not_found(char* arguments, int sock) {
char* error_head = "HTTP/1.0 404 Not Found\r\n";   //构造404错误head
 int len = strlen(error_head);
 if (sendall(sock, error_head, &len) == -1) {    //向客户端发送
  printf("Sending error!");
  return;
 }
char* error_type = "Content-type: text/plain\r\n";
 len = strlen(error_type);
 if (sendall(sock, error_type, &len) == -1) {
  printf("Sending error!");
  return;
 }
char* error_end = "\r\n";
 len = strlen(error_end);
 if (sendall(sock, error_end, &len) == -1) {
  printf("Sending error!");
  return;
 }
char prompt_info[50] = "Not found:  ";
 strcat(prompt_info, arguments);
 len = strlen(prompt_info);
 if (sendall(sock, prompt_info, &len) == -1) {    //输出未找到的文件
  printf("Sending error!");
  return;
 }    
}

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;
 }
if (content_type) {         //content_type不为空
  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;
  }
 }
}

char* file_type(char* arg) {
 char * temp;          //临时字符串指针
 if ((temp=strrchr(arg,'.')) != NULL) {    //取得后缀
  return temp+1;
 }
 return "";           //如果请求的文件名中没有. 则返回空串
}

void send_file(char* arguments, int sock) {
char* extension = file_type(arguments);    //获得文件后缀名
 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";
 }
if (strcmp(extension, "gif") == 0) {    //发送内容为gif
  content_type = "image/gif";
 }
if (strcmp(extension, "jpg") == 0) {    //发送内容为jpg
  content_type = "image/jpg";
 }
read_from = fopen(arguments, "r");     //打开用户指定的文件准备读取
 if(read_from != NULL) {        //指针不为空
  char read_buf[128];        //读文件时的字节缓存数组
  send_header(sock, content_type);    //发送协议头
  send(sock, "\r\n", 2, 0);      //再加一个"\r\n" 不能缺少 格式要求
while(!feof(read_from)) {      //判断文件是否已经结束
   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 command[BUFSIZ];        //保存解析到的命令字段 GET PUT
 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;
 }
if (not_exit(arguments)) {       //请求的文件是否存在  
  file_not_found(arguments, client_sock);
  return;
 }
send_file(arguments, client_sock);     //命令格式及请求路径正确则发送数据
 
 return;
}

int make_server_socket() {
 struct sockaddr_in server_addr;       //服务器地址结构体
int tempSockId;           //临时存储socket描述符
tempSockId = socket(PF_INET, SOCK_STREAM, 0);
 
 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);
if (bind(tempSockId, (struct sockaddr *)&server_addr,
  sizeof(server_addr)) == -1) {       //绑定服务如果出错则返回-1
  printf("bind error!\n");
  return -1;
 }
if (listen(tempSockId, BACKLOG) == -1 ) {     //开始监听
  printf("listen error!\n");
  return -1;
 }
return tempSockId;           //返回取得的SOCKET
}

void main(int argc, char * argv[]) {

 WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
  fprintf(stderr, "WSAStartup failed.\n");
  exit(1);
 }
printf("My web server started...\n");
int server_socket;        //服务器的socket
 int acc_socket;         //接收到的用户连接的socket
 int sock_size = sizeof(struct sockaddr_in);
struct sockaddr_in user_socket;     //客户连接信息
server_socket = make_server_socket();   //创建服务器端的socket
if (server_socket == -1) {      //创建socket出错
  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);
 }
}
分享到:
评论

相关推荐

    (linux下C语言实现)简易web服务器

    2. **多路复用I/O**:为了处理多个并发客户端请求,Web服务器通常会采用多路复用I/O模型,如`select()`, `poll()`或`epoll()`。这些函数可以让服务器监控多个套接字,一旦有任何活动,就可以立即响应,提高服务器的...

    CGI在嵌入式WEB服务器中的应用和实现.pdf

    CGI(Common Gateway Interface,通用网关接口)是一种用于Web服务器与外部程序进行数据交换的协议标准。它的作用是允许客户端浏览器通过HTTP请求与服务器端运行的程序进行交互。CGI通常与HTML表单一起使用,能够...

    web服务器、网站下载、浏览器例程.rar_c web 服务器_web 服务器_web服务器_从web服务器_网络浏览

    在IT领域,Web服务器、网站下载以及浏览器是网络技术中的核心组成部分。Web服务器是一种软件,它接收HTTP(超文本传输协议)请求,并返回相应的HTTP响应,通常为网页内容。在这个主题中,我们将深入探讨这三个主要...

    C语言实现的支持高并发、超高性能Web服务器源码.rar

    C语言实现的支持高并发、超高性能Web服务器源码,可以编译运行,使用高性能HTTP解析器fasterhttp作为其解析核心,在开启Keep-Alive和gzip压缩时(现代浏览器默认开启)性能比nginx约快3倍。 hetao功能: * 支持主流...

    基于ARM-Linux的嵌入式WEB服务器

    基于ARM-Linux的嵌入式WEB服务器设计和实现涉及到多个方面的知识和技能。本文将详细解析嵌入式WEB服务器原理,远程设备监控方法,以及系统软硬件设计的关键细节。 首先,嵌入式WEB服务器是在物联网技术背景下产生的...

    人工智能-项目实践-html-基于标准C库实现嵌入式RTSP服务器.zip

    本Demo基于标准C库编写实现嵌入式RTSP服务器,主要用于网络摄像头/网络录像机提供RTSP直播预览服务 版本:rtsp_demo_20170329 学习RTSP时写的一个简易的RTSP服务器源码 支持H264/H265/aac/g726/G711A流 支持多通道 不...

    嵌入式Web服务器的分析与研究

    这篇文章主要探讨了嵌入式Web服务器的发展背景、支撑技术以及其实现方法。 1. **发展背景** - 随着后PC时代的到来,信息产品逐渐普及,嵌入式Internet技术应运而生。嵌入式系统,即带有微处理器的专用系统,广泛...

    使用 c 语言实现的一个轻量级 web 服务器.zip

    - 使用C语言编写Web服务器需要熟悉标准输入输出、文件操作、内存管理和字符串处理等基本技能。 - 还可能涉及多线程或多进程模型,以处理并发请求。例如,可以使用fork()创建子进程,或者使用pthread库实现线程。 ...

    基于STM32的串口服务器web功能实现.docx

    - `web_server.c`、`web_server.h`:实现Web服务器的核心代码,包括HTTP服务处理和数据交互。 - `cgi_ssi.c`:包含了CGI(Common Gateway Interface)和SSI(Server Side Include)的处理逻辑。CGI用于接收和处理...

    嵌入式Web服务器移植

    而"ARM平台上嵌入式Web服务器实现[1].pdf"和两本关于ARM应用开发的书籍,即"《嵌入式Linux开发详解——基于EP93XX系列ARM》.rar"和"《ARM应用系统开发详解——基于S3C4510B的系统设计(第二版)》.rar",则为在ARM...

    嵌入式Linux Web服务器的实现与应用.pdf

    《嵌入式Linux Web服务器的实现与应用》这篇文章主要探讨了如何在嵌入式设备上构建和应用Linux Web服务器,以及在硬件和软件层面实现的关键技术和方案。文章首先介绍了嵌入式Linux Web服务器的设计原则和应用场景,...

    基于STM32的串口服务器web功能实现.pdf

    4. `httpd.c`:实现了将串口服务器配置为Web服务器的功能。 5. `httpd.h`:HTTP服务器相关的头文件。 6. `httpd_cgi_ssi.c`:包含CGI和SSI(服务器端包含)的源文件,用于处理网页配置请求。 网页制作方面,通常...

    linux c web服务器简单实现.docx

    Linux C Web服务器的实现涉及到网络编程、HTTP协议、文件系统操作等多个方面。下面将详细介绍四个小型Web服务器项目:micro_httpd、mini_httpd、thttpd和lighttpd,以及它们各自的特点和适用场景。 1. **micro_...

    C语言搭建的简单web服务器

    本项目以"C语言搭建的简单web服务器"为主题,展示了如何利用C语言实现一个基础的Web服务器,支持网页访问和简单的CGI(Common Gateway Interface)功能。下面我们将深入探讨相关知识点。 1. **Web服务器基础** Web...

    WebServer.zip_Web 文件服务_web服务器

    c)利用HTML语言编写网页(可以不包括图像、声音等多媒体文件),浏览器可通过编写的Web服务器正常访问该网页; d)支持多用户并发访问; e)在Windows平台下,采用C/C++语言; f)扩展编写的简单Web服务器,使...

    嵌入式Web服务器的设计与实现.pdf

    CGI是一种标准,用于使Web服务器与外部程序交互,以动态生成网页内容。在嵌入式Web服务器中,CGI脚本可以用来处理来自用户的输入,执行设备控制逻辑,并返回相应的网页响应。 3. **硬件平台** 文中以S3C2410...

    标准C语言编写的Web服务器完成HTTP 请求

    linux平台下使用标准C语言编写的Web服务器,代码简单易懂,适合新手.do_trans.c为完成请求主要实现代码,servers.c为shock建立实现代码,默认端口6666,网页根目录/home/wwwroot

    嵌入式WEB服务器及远程测控应用详解

    本教程将深入探讨嵌入式WEB服务器在远程测控应用中的实现与应用。 一、嵌入式WEB服务器的基本原理 嵌入式WEB服务器的工作原理与传统的WEB服务器类似,主要由HTTP服务器、HTML文档、CGI(通用网关接口)以及可能的...

    轻量级Web服务器选择

    轻量级Web服务器可以通过多种编程语言实现,包括但不限于C、Erlang、Java、Lisp、Lua、Perl、Python和Tcl等。 - **C语言**:许多轻量级Web服务器都是用C语言编写的,因为C语言能够提供更好的性能和较低的资源消耗。...

Global site tag (gtag.js) - Google Analytics