`

简单http_server的C语言实现

阅读更多
主要实现以下几点:

1.静态文件访问,包括jpg、html、css等

2.文件不存在404

3.目录列表

4.501 Not Implemented

=============================================================================

启动脚本
#!/bin/sh

ps -ef | grep fasthttp | grep -v grep | awk '{print $2}' | xargs -t -i kill -9 {} >/dev/null
gcc   fasthttp.c -o fasthttp
$(pwd)/fasthttp


以下是源码

=====================================================================================
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <error.h>
#include <errno.h>

#include <sys/types.h>
#include <dirent.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

// 建立socket 开始侦听 接收连接 接收客户端数据 解析http协议 发送文件数据给客户端

#define HTTP_PORT "2010"
#define MAX_CONNECTION 10
#define DOCUMENT_ROOT "www"
#define LOG_PATH "log/access.log"

void parser(char *s,char res[][255],char host[][255]);
static char *strtoupper( char *s );
static long filesize(const char *filename);
static int file_exists(const char *filename);
static void mime_content_type( const char *name, char *ret );
static int WriteLog( const char *message );
static int is_dir(const char *filename);

static unsigned short g_is_log        = 1;
static int g_log_fd                    = 0;

int main(void)
{
    int server_sock;
    int client_sock;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    struct sockaddr_in sin;
    struct stat file_stat;
    pid_t pid;
    char client_ip[100];
    char buf[20000];
    char buf_all[2000];
    char buf1[2000];
    char p[3][255];
    char h[3][255];
    char tmp[2000];
    char cwd[1024];
    char filename[2000];
    char filepath[2000];
    int fd,size;
    int currentConn = 0;
    
    DIR * dir;
    struct dirent * ptr;
    


    chdir("../");
    
    if ( (pid = fork()) < 0 )
    {
        perror("fork");
        exit(1);
    }
    else if ( pid != 0)
    {
        exit(1);
    }
    
    if((server_sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
    {
        perror("socket");
        exit(1);
    }
    
    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(HTTP_PORT));
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    if(bind(server_sock,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)
    {
        perror("bind");
        exit(1);
    }
    
    if(listen(server_sock,MAX_CONNECTION) < 0)
    {
        perror("listen");
        exit(1);
    }
    
    printf("fasthttp successful created ...\n");
    
    while(1)
    {
        unsigned int clientlen = sizeof(client_addr);
        if((client_sock = accept(server_sock,(struct sockaddr*)&client_addr,&clientlen)) < 0)
        {
            perror("accept");
            exit(1);
        }
        
        if((pid = fork()) == 0)
        {

            if(read(client_sock,buf,20000) < 0)
            {
                perror("read data from client");
                exit(1);
            }
            
            parser(buf,p,h);
            
            if(strcmp(strtoupper(p[0]),"GET") != 0
                && strcmp(strtoupper(p[0]),"POST") != 0
                && strcmp(strtoupper(p[0]),"HEAD") != 0)
            {
                memset(&buf,0,sizeof(buf));
                
                sprintf(buf, "HTTP/1.1 501 Not Implemented\r\nServer: %s\r\nContent-Type: text/html\r\nContent-Length:    1489\r\nAccept-Ranges: bytes\r\nConnection: close\r\n\r\n", "Apache");
                write(client_sock,buf,strlen(buf));
                
                memset(&buf,0,sizeof(buf));
                sprintf(buf,"<h2>%s Method Not Implemented</h2>","501");
                write(client_sock,buf,strlen(buf));
                close(client_sock);
                exit(0);
            }
             
            if(strcmp(p[1],"/") == 0)
            {
                memset(&tmp,0,sizeof(tmp));
                sprintf(tmp,"%s","index.html");
                strcat(p[1],tmp);
            }
            
            WriteLog(p[1]);
            getcwd(filepath, sizeof(filepath));
            strcat(filepath,"/");
            strcat(filepath,DOCUMENT_ROOT);
             strcat(filepath,p[1]);

            if(!file_exists(filepath))
            {
                memset(&buf,0,sizeof(buf));
                sprintf(buf, "HTTP/1.1 404 Not Found\r\nServer: %s\r\nContent-Type: text/html\r\nContent-Length:    257271\r\nConnection: close\r\n\r\n", "Apache");
                write(client_sock,buf,strlen(buf));
                
                memset(&buf,0,sizeof(buf));
                sprintf(buf,"<html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr><center>Powered by %s</center></body></html>","fasthttp");
                write(client_sock,buf,strlen(buf));
                close(client_sock);
                
                memset(&buf,0,sizeof(buf));
                sprintf(buf,"404 Not Found\t%s\n",filepath);
                WriteLog(buf);
                
                exit(0);
            }
            
            if(access(filepath,R_OK) < 0)
            {
                memset(&buf,0,sizeof(buf));
                sprintf(buf, "HTTP/1.1 403 Forbidden\r\nServer: %s\r\nContent-Type: text/html\r\nContent-Length:    25727\r\nConnection: close\r\n\r\n", "Apache");
                write(client_sock,buf,strlen(buf));
                close(client_sock);
                exit(0);
            }
            
             /** 目录列表 **/
             if(is_dir(filepath))
             {
                memset(&tmp,0,sizeof(tmp));
                sprintf(tmp,"<html><head><title>Index of %s</title></head><body><h1>Index of %s</h1><ul><li><a href=\"/\"> Parent Directory</a></li>",filepath,filepath);
                strcat(buf,tmp);

                 if((dir = opendir(filepath)) != NULL)
                 {
                     while((ptr = readdir(dir)) != NULL)
                     {
                         
                         if(strcmp(ptr->d_name,".") == 0 || strcmp(ptr->d_name,"..") == 0)
                         {
                             continue;    
                         }
                         
                         memset(&buf,0,sizeof(buf));
                         sprintf(buf,"%s/%s",filepath,ptr->d_name);
                        
                        if(is_dir(buf))
                        {
                            memset(&buf,0,sizeof(buf));
                            sprintf(buf,"<li><a href=\"%s/\"> %s/</a></li>",ptr->d_name,ptr->d_name);
                        }
                        else
                        {
                            memset(&buf,0,sizeof(buf));
                            sprintf(buf,"<li><a href=\"%s\"> %s</a></li>",ptr->d_name,ptr->d_name);    
                        }
                        strcat(tmp,buf);
                     }
                 }
                 closedir(dir);

                 memset(&buf,0,sizeof(buf));
                sprintf(buf,"%s","</ul>");
                strcat(tmp,buf);
                
                memset(&buf,0,sizeof(buf));
                sprintf(buf, "HTTP/1.1 200 OK\r\nServer: fasthttp\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length:    %d\r\nConnection: close\r\n\r\n", strlen(tmp));
                write(client_sock,buf,strlen(buf));
            
                write(client_sock,tmp,strlen(tmp));
                close(client_sock);
             }
             
            memset(&tmp,0,sizeof(tmp));
            mime_content_type(filepath,tmp);
            
            memset(&buf,0,sizeof(buf));
            sprintf(buf, "HTTP/1.1 200 OK\r\nServer: %s\r\nContent-Type: %s\r\nContent-Length:    25727\r\nConnection: close\r\n\r\n", "Apache",tmp);
            write(client_sock,buf,strlen(buf));
            
            
            
            memset(&buf,0,sizeof(buf));
            fd = open(filepath,O_RDONLY);
            read(fd,buf,filesize(filepath));
            close(fd);
            
            write(client_sock,buf,filesize(filepath));
            close(client_sock);
            
            memset(&buf,0,sizeof(buf));
            sprintf(buf,"200 OK\t%s\t%d\n",filepath,filesize(filepath));
            WriteLog(buf);
            
            exit(0);
        }
        else
        {
            wait(NULL);
        }
        
        close(client_sock);
    }
    
    
}

void parser(char *s,char res[][255],char host[][255])
{
    int i,j = 0;
    int n;
    char hosts[255];

    for (i = 0;s[i] != '\r';i++)        /* obtain the first line in http protocol head */
        ;
    s[i] = '\0';
    n=i++;
    
    for (i = 0,j = 0;i < 3;i++,j++)        /* divide the protocol head in blank */
    {
        strcpy(res[j],strsep(&s," "));
    }
    
    for(i=n;s[i] != '\r';i++)
    {
        strcat(hosts,s[i]);
    }
    
    for (i = 0,j = 0;i < 3;i++,j++)        /* divide the protocol head in blank */
    {
        strcpy(host[j],strsep(&hosts,":"));
    }
    
}

/**
 * strtoupper - string to upper
 *
 */
static char *strtoupper( char *s )
{
    int i, len = sizeof(s);
    for( i = 0; i < len; i++ )
    {
        s[i] = ( s[i] >= 'a' && s[i] <= 'z' ? s[i] + 'A' - 'a' : s[i] );
    }
    
    return(s);
}

/**
 *  filesize - get file size
 */
static long filesize(const char *filename)
{
    struct stat buf;
    if (!stat(filename, &buf))
    {
        return buf.st_size;
    }
    return 0;
}

/**
 * file_exists - check file is exist
 */
static int file_exists(const char *filename)
{
    struct stat buf;
    
    if (stat(filename, &buf) < 0)
    {
        if (errno == ENOENT)
        {
            return 0;
        }
    }
    return 1;
}

/**
 * Get MIME type header
 *
 */
static void mime_content_type( const char *name, char *ret ){
    char *dot, *buf;

    dot = strrchr(name, '.');

    /* Text */
    if ( strcmp(dot, ".txt") == 0 ){
        buf = "text/plain";
    } else if ( strcmp( dot, ".css" ) == 0 ){
        buf = "text/css";
    } else if ( strcmp( dot, ".js" ) == 0 ){
        buf = "text/javascript";
    } else if ( strcmp(dot, ".xml") == 0 || strcmp(dot, ".xsl") == 0 ){
        buf = "text/xml";
    } else if ( strcmp(dot, ".xhtm") == 0 || strcmp(dot, ".xhtml") == 0 || strcmp(dot, ".xht") == 0 ){
        buf = "application/xhtml+xml";
    } else if ( strcmp(dot, ".html") == 0 || strcmp(dot, ".htm") == 0 || strcmp(dot, ".shtml") == 0 || strcmp(dot, ".hts") == 0 ){
        buf = "text/html";

    /* Images */
    } else if ( strcmp( dot, ".gif" ) == 0 ){
        buf = "image/gif";
    } else if ( strcmp( dot, ".png" ) == 0 ){
        buf = "image/png";
    } else if ( strcmp( dot, ".bmp" ) == 0 ){
        buf = "application/x-MS-bmp";
    } else if ( strcmp( dot, ".jpg" ) == 0 || strcmp( dot, ".jpeg" ) == 0 || strcmp( dot, ".jpe" ) == 0 || strcmp( dot, ".jpz" ) == 0 ){
        buf = "image/jpeg";

    /* Audio & Video */
    } else if ( strcmp( dot, ".wav" ) == 0 ){
        buf = "audio/wav";
    } else if ( strcmp( dot, ".wma" ) == 0 ){
        buf = "audio/x-ms-wma";
    } else if ( strcmp( dot, ".wmv" ) == 0 ){
        buf = "audio/x-ms-wmv";
    } else if ( strcmp( dot, ".au" ) == 0 || strcmp( dot, ".snd" ) == 0 ){
        buf = "audio/basic";
    } else if ( strcmp( dot, ".midi" ) == 0 || strcmp( dot, ".mid" ) == 0 ){
        buf = "audio/midi";
    } else if ( strcmp( dot, ".mp3" ) == 0 || strcmp( dot, ".mp2" ) == 0 ){
        buf = "audio/x-mpeg";
    } else if ( strcmp( dot, ".rm" ) == 0  || strcmp( dot, ".rmvb" ) == 0 || strcmp( dot, ".rmm" ) == 0 ){
        buf = "audio/x-pn-realaudio";
    } else if ( strcmp( dot, ".avi" ) == 0 ){
        buf = "video/x-msvideo";
    } else if ( strcmp( dot, ".3gp" ) == 0 ){
        buf = "video/3gpp";
    } else if ( strcmp( dot, ".mov" ) == 0 ){
        buf = "video/quicktime";
    } else if ( strcmp( dot, ".wmx" ) == 0 ){
        buf = "video/x-ms-wmx";
    } else if ( strcmp( dot, ".asf" ) == 0  || strcmp( dot, ".asx" ) == 0 ){
        buf = "video/x-ms-asf";
    } else if ( strcmp( dot, ".mp4" ) == 0 || strcmp( dot, ".mpg4" ) == 0 ){
        buf = "video/mp4";
    } else if ( strcmp( dot, ".mpe" ) == 0  || strcmp( dot, ".mpeg" ) == 0 || strcmp( dot, ".mpg" ) == 0 || strcmp( dot, ".mpga" ) == 0 ){
        buf = "video/mpeg";

    /* Documents */
    } else if ( strcmp( dot, ".pdf" ) == 0 ){
        buf = "application/pdf";
    } else if ( strcmp( dot, ".rtf" ) == 0 ){
        buf = "application/rtf";
    } else if ( strcmp( dot, ".doc" ) == 0  || strcmp( dot, ".dot" ) == 0 ){
        buf = "application/msword";
    } else if ( strcmp( dot, ".xls" ) == 0  || strcmp( dot, ".xla" ) == 0 ){
        buf = "application/msexcel";
    } else if ( strcmp( dot, ".hlp" ) == 0  || strcmp( dot, ".chm" ) == 0 ){
        buf = "application/mshelp";
    } else if ( strcmp( dot, ".swf" ) == 0  || strcmp( dot, ".swfl" ) == 0 || strcmp( dot, ".cab" ) == 0 ){
        buf = "application/x-shockwave-flash";
    } else if ( strcmp( dot, ".ppt" ) == 0  || strcmp( dot, ".ppz" ) == 0 || strcmp( dot, ".pps" ) == 0 || strcmp( dot, ".pot" ) == 0 ){
        buf = "application/mspowerpoint";

    /* Binary & Packages */
    } else if ( strcmp( dot, ".zip" ) == 0 ){
        buf = "application/zip";
    } else if ( strcmp( dot, ".rar" ) == 0 ){
        buf = "application/x-rar-compressed";
    } else if ( strcmp( dot, ".gz" ) == 0 ){
        buf = "application/x-gzip";
    } else if ( strcmp( dot, ".jar" ) == 0 ){
        buf = "application/java-archive";
    } else if ( strcmp( dot, ".tgz" ) == 0  || strcmp( dot, ".tar" ) == 0 ){
        buf = "application/x-tar";
    } else {
        buf = "application/octet-stream";
    }
    strcpy(ret, buf);
}

/**
 * Log message
 *
 */
static int WriteLog( const char *message )
{
    if ( !g_is_log )
    {
        fprintf(stderr, "%s", message);
        return 0;
    }
    if ( g_log_fd == 0 )
    {
        char g_log_path[2000];
        getcwd(g_log_path, sizeof(g_log_path));
        strcat(g_log_path,"/");
        strcat(g_log_path,LOG_PATH);
        
        if ( (g_log_fd = open(g_log_path, O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1 )
        {
            perror("open log file error");
            return -1;
        }
    }
    
    if (write(g_log_fd, message, strlen(message)) == -1)
    {
        perror("write log error");
        return -1;
    }

    return 0;
}

/**
 * is_dir - check file is directory
 *
 */
static int is_dir(const char *filename){
    struct stat buf;
    if ( stat(filename, &buf) < 0 ){
        return -1;
    }
    if (S_ISDIR(buf.st_mode)){
        return 1;
    }
    return 0;
}
0
0
分享到:
评论

相关推荐

    chat_server_C语言_TCP/IP_

    【标题】"chat_server_C语言_TCP/IP_" 描述了一个使用C语言实现的基于TCP协议的简单聊天服务器。这个项目的核心在于其设计和实现了一个能够处理客户端连接和通信的基础架构,使得多个用户可以通过网络进行实时文本...

    udp_server.zip_UDP C语言

    总的来说,这个“udp_server.c”程序展示了如何在Linux环境下使用C语言构建一个简单的UDP服务器,监听特定端口,接收和响应客户端数据。学习这个程序可以帮助理解UDP通信的基本流程和C语言在网络编程中的应用。

    linux平台下C语言实现一个简单的httpsever

    在Linux平台上,使用C语言实现一个简单的HTTP服务器是一项基础但重要的技能,这涉及到网络编程、多线程处理以及文件操作等多个领域。以下是一些相关的知识点: 1. **TCP/IP协议与HTTP协议**: - TCP(传输控制协议...

    http_test.rar_Linux C http_POST 文件 HTTP_The Test_c http_c语言 h

    在IT行业中,网络编程是不可或缺的一部分,特别是在C语言环境下实现HTTP协议的POST方法来上传文件,这是一项基础但重要的技能。本文将详细讲解如何利用C语言在Linux系统中实现HTTP POST请求,上传文件到服务器。 ...

    telnet-server-for-linux.zip_telnet c语言_telnet linux c++_telnet s

    通过阅读和分析这份代码,我们可以了解如何在Linux下使用C语言或C++实现一个简单的telnet服务器,包括套接字创建、绑定、监听、接受连接、读写数据等步骤。"readme.txt"可能包含关于如何编译和运行服务器的说明,...

    C语言实现webserver

    本主题“C语言实现webserver”旨在介绍如何使用C语言编写一个简单的Web服务器,这对于理解HTTP协议、网络编程以及C语言的实际应用具有重要意义。 一、Web服务器基础 Web服务器是互联网基础设施的关键组成部分,它...

    C语言实现的websocket

    为了测试和调试C语言实现的WebSocket客户端,通常会配合一个简单的HTML页面,利用浏览器的WebSocket API。HTML页面可以创建一个WebSocket对象,连接到C客户端运行的本地服务器,然后通过JavaScript发送和接收数据,...

    C语言与SQL_server连接

    在本文中,我们将探讨如何使用C语言连接到SQL Server 2008数据库,以及在这个过程中涉及的...通过掌握这些知识点,你可以编写C语言程序,实现与SQL Server的交互,执行CRUD(创建、读取、更新、删除)等数据库操作。

    fws.rar_HTTP WEB SERVER_gzip_http gzip_http server_http server c

    "gzip_http server"表明这个Web服务器支持GZIP压缩,这是一种常见的HTTP数据压缩方法,用于减少网络传输的数据量,提高网页加载速度。 HTTP Web服务器是互联网基础设施的重要组成部分,它接收客户端(通常是浏览器...

    TCP通讯的C语言实现

    本资源提供了一种使用C语言实现TCP客户端和服务器程序的方法,这对于理解TCP协议的工作原理以及进行实际编程实践具有极大的帮助。 TCP是一种面向连接的协议,它在数据传输前先建立连接,确保了数据的有序性和可靠性...

    udp 多播 c语言实现

    这个简单的示例展示了如何在C语言中实现UDP多播的基本功能。在实际应用中,你可能还需要处理错误,添加多线程或异步I/O来提高性能,以及使用更复杂的多播选项,比如设定多播TTL(Time To Live)来控制多播数据的传播...

    Http.rar_C http server_c# http_http c#_http c++_http server

    标题中的"Http.rar_C http server_c# http_http c#_http c++_http server"表明这是一个关于HTTP服务器的资源集合,涉及到C、C#以及C++三种编程语言。描述中的"Http concurrent server"则提示我们这可能是一个支持...

    async_client_server_II_src.zip_http client_http client server

    标题"async_client_server_II_src.zip_http client_http client server"暗示了这是一个关于异步客户端-服务器模型的源代码压缩包,它涉及到了HTTP客户端和服务器的实现。让我们深入了解一下这个主题。 HTTP(超文本...

    作业1_利用C语言在控制台上实现TCP套接字数据传输.pdf

    实现了一个简单的 TCP 服务器,用于监听指定端口的连接请求并与客户端进行通信。当客户端连接成功后,服务器端向客户端发送“Hello World!”消息,并在完成通信后关闭套接字并清理资源。 源代码如下: ```c #...

    Linux- 用C语言实现的简单Web服务器源代码

    本文将深入探讨由熊第彬所编写的"Linux- 用C语言实现的简单Web服务器源代码",它是一个轻量级的Web服务器示例,可以帮助初学者理解HTTP协议和网络编程的基本原理。 首先,让我们了解一下Web服务器的工作原理。Web...

    对讲机_socket编程_c语言对讲机_

    C语言实现时,会使用`socket()`函数创建套接字,`bind()`函数绑定套接字到特定的IP和端口,`listen()`函数使服务器进入监听状态,`accept()`函数接收新的连接请求,最后`recvfrom()`和`sendto()`函数用于接收和发送...

    c语言实现简易版http server,支持GET,POST CGI 程序,fork-and-execute.zip

    c语言实现简易版http server,支持GET,POST CGI 程序,fork-and-execute管理服务器基本信息C语言实现简易版http server,目前支持GET,POST,CGI程序cgi-bin 目录主要包含cig程序static 目录主要是静态资源运行方式./...

    Tiny-WebServer-master一个微web服务器, 纯c语言实现

    总的来说,Tiny-WebServer-master是一个实用的学习工具,它展示了如何使用C语言实现一个简单的Web服务器,同时提供了深入研究网络编程和Web服务器架构的机会。无论是对个人学习还是团队项目,都具有很高的价值。

    C语言http客户端通信实现

    本文将深入探讨如何使用C语言实现一个简单的HTTP客户端,以便于理解网络通信的基本原理和C语言在网络编程中的应用。 首先,我们要了解HTTP(超文本传输协议)的基本概念。HTTP是互联网上应用最广泛的一种网络协议,...

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

    在Linux环境下,使用C语言编写一个简易的Web服务器是一项具有挑战性的任务,它涉及到网络编程、HTTP协议理解和操作系统层面的知识。下面将详细讲解这个项目所涵盖的关键知识点。 首先,我们来了解一下C语言在网络...

Global site tag (gtag.js) - Google Analytics