基于C语言编写一个简单的Web服务器

 更新时间:2024年03月11日 09:50:38   作者:自信人间三百年  
C语言可以干大事,这篇文章主要为大家详细介绍了如何基于C语言可以完成一个简易的Web服务器,希望这篇文章会帮你你对C语言有更深入的理解

概述

C语言可以干大事,我们基于C语言可以完成一个简易的Web服务器。当你能够自行完成web服务器,你会对C语言有更深入的理解。对于网络编程,字符串的使用,文件使用等等都会有很大的提高。

关于网络的TCP协议在这里不在多说,大家可以查阅些资料。

工具

开发工具: CLion,编译器

演示效果图

创建socket对象

int server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

​​​​​​​if (0 > server_socket) {
    printf("[服务器] 创建socket对象失败,服务器启动失败...\n");
    return -1;
}
printf("[服务器] 创建socket成功....\n");

绑定服务器端口

struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);


int bind_ret = bind(server_socket, (struct  sockaddr*) &my_addr, sizeof(my_addr));

if (0 > bind_ret) {
    printf("[服务器]绑定端口%d失败,服务器启动失败\n", PORT);
    return -2;
}
printf("[服务器] 绑定端口:%d成功....\n", PORT);

监听服务器端口

int listen_ret = listen(server_socket, BACK_LOG);
if (0 > listen_ret) {
    printf("监听端口:%d失败,服务器运行失败....\n", PORT);
    return -3;
}
printf("[服务器] 监听端口:%d成功....\n", PORT);

建立连接

struct sockaddr_in accept_in;
socklen_t socklen = sizeof(accept_in);
int accept_socket = accept(server_socket, (struct sockaddr *) &accept_in, &socklen);

if (-1 == accept_socket) {
    printf("[服务器] 接收请求失败,建立连接失败... \n");
    return -4;
}
printf("[服务器] 建立连接成功....\n");

获取客户端请求

char buffer[BUFFER_SIZE];
memset(buffer, 0, sizeof(buffer));
ssize_t data = recv(accept_socket, buffer, sizeof(buffer), RECV_FLAG);


if (data == 0) {
    printf("[服务器] 超时或对端主动关闭...\n");
    break;
}
if (0 > data) {
    printf("[服务器] 接收数据失败...\n");
    break;
}

printf("[服务器] 与客户端建立连接成功...\n");

启动服务器

[服务器] 创建socket成功....
[服务器] 绑定端口:9999成功....
[服务器] 监听端口:9999成功....
[服务器] 建立连接成功....
[服务器] 与客户端建立连接成功...

解析前端(浏览器)发起的请求

tips: 本次只处理前端GET方式请,即标签,或者从浏览器直接发起请求。

解析客户端请求

此次项目获取的页面GET请求。

char req[100];
memset(req, 0, sizeof(req));

get_method_req(req_buffer, req);
url_decode(req);
printf("[服务器] 来自客户端的请求==>%s\n", req);

定义字符数组存储请求数据

char req[100];
memset(req, 0, sizeof(req));

将请求数据写入req数组

void get_method_req(char *req_buff, char *req);
void get_method_req(char *req_buff, char *req) {
    int count = 0;
    for (int i = 6; i < strlen(buffer); i++) {
        if (buffer[i] == ' ') {
            break;
        }
        res[count++] = buffer[i];
    }
    res[count] = '\0';
}

将浏览器中的数据重新编码

浏览器会对中文进行编码,我们需要将其重新解码回中文形式。

int hex2dec(char c);
void url_decode(char url[]);

int hex2dec(char c) {
    if ('0' <= c && c <= '9') {
        return c - '0';
    } else if ('a' <= c && c <= 'f') {
        return c - 'a' + 10;
    } else if ('A' <= c && c <= 'F') {
        return c - 'A' + 10;
    } else {
        return -1;
    }
}

void url_decode(char url[]) {
    int i = 0;
    int len = strlen(url);
    int res_len = 0;
    char res[100];
    for (i = 0; i < len; ++i) {
        char c = url[i];
        if (c != '%') {
            res[res_len++] = c;
        } else {
            char c1 = url[++i];
            char c0 = url[++i];
            int num = 0;
            num = hex2dec(c1) * 16 + hex2dec(c0);
            res[res_len++] = num;
        }
    }
    res[res_len] = '\0';
    strcpy(url, res);
}

运行结果

问题:如何关闭windows进程

如果在启动web服务器时出现以下问题

查询指定端口

netstat -aon | findstr 端口号

netstat -aon|findstr 9999

终止指定进程

taskkill /f /t /im 进程ID

taskkill /f /t /im 10200

到此这篇关于基于C语言编写一个简单的Web服务器的文章就介绍到这了,更多相关C语言编写Web服务器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言 指针综合解析

    C语言 指针综合解析

    指针可以表示一个变更的地址,在计算机程序中,通常表示内存地址,存储数据的地址,下面这篇文章主要给大家综合的介绍了关于C语言指针的本质与用法
    2021-11-11
  • c++ Qt信号槽原理

    c++ Qt信号槽原理

    这篇文章主要介绍了c++ Qt信号槽原理的相关资料,帮助大家更好的理解和使用c++,感兴趣的朋友可以了解下
    2021-02-02
  • 利用C++实现⾃然连接操作算法

    利用C++实现⾃然连接操作算法

    这篇文章主要介绍了利用C++实现⾃然连接操作算法,文章围绕主题展开详细的内容介绍,具有一定参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • C++实现本地TCP通讯的示例代码

    C++实现本地TCP通讯的示例代码

    这篇文章主要为大家详细介绍了C++如何利用TCP技术,实现本地ROS1和ROS2的通讯,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-02-02
  • 如何在C++中调用python代码你知道吗

    如何在C++中调用python代码你知道吗

    这篇文章主要为大家介绍了C++中调用python代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • C++ 自增、自减运算符的重载和性能分析小结

    C++ 自增、自减运算符的重载和性能分析小结

    这篇文章主要介绍了C++ 自增、自减运算符的重载和性能分析小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • C++实现单词管理系统

    C++实现单词管理系统

    这篇文章主要为大家详细介绍了C++实现单词管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • QT实现用户登录注册功能

    QT实现用户登录注册功能

    这篇文章主要为大家详细介绍了QT实现用户登录注册功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C++ EasyX学习之鼠标操作详解

    C++ EasyX学习之鼠标操作详解

    EasyX是针对C/C++的图形库,可以帮助使用C/C++语言的程序员快速上手图形和游戏编程。本文将为大家详细讲讲EasyX的鼠标操作,需要的可以参考一下
    2022-07-07
  • 基于Matlab LBP实现植物叶片识别功能

    基于Matlab LBP实现植物叶片识别功能

    局部二值模式(LBP)是由Ojala等人于2002年提出,它被用于特征提取,而且提取的特征是图像的纹理特征。本文将利用Matlab和LBP实现植物叶片识别,需要的可以参考一下
    2022-02-02

最新评论