| 网站首页 | 业界新闻 | 小组 | 交易 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
共有 780 人关注过本帖, 1 人收藏
标题:[原创] 100 多行代码,实现了一个简单的 http 服务器
只看楼主 加入收藏
RockCarry
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:7
帖 子:639
专家分:58
注 册:2005-8-5
结帖率:94.44%
  已结贴   问题点数:20  回复次数:8   
[原创] 100 多行代码,实现了一个简单的 http 服务器
代码地址:
https://


也可以直接下载压缩包:

附件: 您没有浏览附件的权限,请 登录注册
搜索更多相关主题的帖子: 多行 代码 http 服务器 压缩包 
2019-08-14 11:27
RockCarry
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:7
帖 子:639
专家分:58
注 册:2005-8-5
  得分:0 
ffhttpd.c

程序代码:
#include <stdlib.h>  
#include <stdio.h >  
#include <string.h>

#ifdef __WIN32__
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define  closesocket close
#endif

#define FFHTTPD_SERVER_PORT     8080
#define FFHTTPD_MAX_CONNECTION  100

static char *g_ffhttpd_head = 
"HTTP/1.1 200 OK\r\n"
"Server: ffhttpd/1.0.0\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %d\r\n"
"Accept-Ranges: bytes\r\n"
"Connection: close\r\n\r\n";

static int file_load(char *path, char **data)
{
    char *buffer   = NULL;
    int   filesize = 0;
    FILE *fp       = NULL;
    if (!path || !data) return 0;
    fp = fopen(path, "rb");
    if (fp) {
        fseek(fp, 0, SEEK_END);
        filesize = ftell(fp);
        fseek(fp, 0, SEEK_SET);
        buffer = malloc(filesize);
        if (buffer) fread(buffer, filesize, 1, fp);
        fclose(fp);
    }
    *data = buffer;
    return filesize;
}

static void file_free(char **data)
{
    if (data) {
        free(*data);
        *data = NULL;
    }
}

static void parse_string(char *str, char *path, int size)
{
    char *src_start = NULL;
    char *src_end   = NULL;
    char *dst_end   = path + size;
    src_start = strstr(str, "GET /");
    if (src_start) {
        src_start += 5;
        src_end = strstr(src_start, " ");
        while (src_start < src_end && path < dst_end) *path++ = *src_start++;
        if (path == dst_end) path--;
    }
    *path = 0;
}

int main(void)
{
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int    server_fd, conn_fd, addrlen, length;
    char   buffer[1024], path[1024], *filedata;

#ifdef __WIN32__
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        exit(1);
    }
#endif

    server_addr.sin_family      = AF_INET;
    server_addr.sin_port        = htons(FFHTTPD_SERVER_PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        printf("failed to open socket !\n");
        exit(1);
    }

    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
        printf("failed to bind !\n");
        exit(1);
    }

    if (listen(server_fd, FFHTTPD_MAX_CONNECTION) == -1) {
        printf("failed to listen !\n");
        exit(1);
    }

    addrlen = sizeof(client_addr);
    while (1) {
        conn_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addrlen);
        if (conn_fd == -1) {
            printf("failed to accept !\n");
            continue;
        }

        length = recv(conn_fd, buffer, sizeof(buffer), 0);
        buffer[length] = 0;
        printf(buffer); fflush(stdout);
        parse_string(buffer, path, sizeof(path));
        if (!path[0]) strcpy(path, "index.html");
        length = file_load(path, &filedata);
        snprintf(buffer, sizeof(buffer), g_ffhttpd_head, length);
        if (1     ) send(conn_fd, buffer, strlen(buffer), 0);
        if (length) send(conn_fd, filedata, length, 0);
        file_free(&filedata);
        closesocket(conn_fd);
    }

    closesocket(server_fd);
#ifdef __WIN32__
    WSACleanup();
#endif
}


2019-08-14 11:28
RockCarry
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:7
帖 子:639
专家分:58
注 册:2005-8-5
  得分:0 
编译方法:

msys2 + mingw 环境下:
gcc ffhttpd.c -Wall -lws2_32 -o ffhttpd.exe

vs2005 环境下应该也可以编译,要自己建一个工程试下
2019-08-14 11:29
RockCarry
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:7
帖 子:639
专家分:58
注 册:2005-8-5
  得分:0 
100 多行代码实现了一个简单的 http 服务器

端口 8080
实现了对 GET 请求的支持

测试方法:
1. 运行 ffhttpd.exe
2. ffhttpd.exe 所在目录放 html 文件,比如 index.html
3. 打开浏览器输入 http://localhost:8080/index.html

就可以看到网页了
2019-08-14 11:29
燕小六
Rank: 4
来 自:北京
等 级:业余侠客
威 望:3
帖 子:49
专家分:247
注 册:2017-11-29
  得分:20 
很不错
2019-08-14 13:15
RockCarry
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:7
帖 子:639
专家分:58
注 册:2005-8-5
  得分:0 
刚提交了最新代码,实现多线程模式,实现 partial 的 GET 请求支持。
代码在 visual studio, msys+mingw, ubuntu+gcc 下均可编译通过。
2019-08-16 17:00
freejzh
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2019-8-24
  得分:0 
回复 楼主 RockCarry
谢谢大佬的开源,我下载下来仔细学习一下。特别感谢开源精神!
2019-08-24 02:04
星泪成寒
Rank: 4
等 级:业余侠客
威 望:3
帖 子:50
专家分:285
注 册:2013-5-19
  得分:0 
没有多路复用, 不支持事件驱动
2019-09-12 17:11
RockCarry
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:7
帖 子:639
专家分:58
注 册:2005-8-5
  得分:0 
100 行代码你能做点啥?并且还是不使用任何第三方库的实现。

代码写复杂了很多人就看不懂了。

GitHub 上的代码已经增加了线程池。至于事件驱动,本身就不是 http 服务器的特征。
2019-09-15 09:45
快速回复:[原创] 100 多行代码,实现了一个简单的 http 服务器
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.062788 second(s), 8 queries.
Copyright©2004-2019, BCCN.NET, All Rights Reserved