【网络编程】如何创建一个自己的并发服务器?

hello !大家好呀! 欢迎大家来到我的网络编程系列之如何创建一个自己的并发服务器,在这篇文章中,你将会学习到在Linux内核中如何创建一个自己的并发服务器,并且我会给出源码进行剖析,以及手绘UML图来帮助大家来理解,希望能让大家更能了解网络编程技术!!!

希望这篇文章能对你有所帮助,大家要是觉得我写的不错的话,那就点点免费的小爱心吧!

如何创建高并发服务器

对于如何创建一个自己的并发服务器,我们首先需要了解框架,就比如一个简单的shttpd服务器,其框架如图:

在其中我们要知道这个框架能实现什么功能,有什么作用。

那么我们知道了这个微型服务器的大致框架,我们就要运用到代码上:

创建一个自己的并发 HTTP 服务器(shttpd)涉及到网络编程和 HTTP 协议的实现。以下是一个基本的步骤指南,用于在 Linux 系统上使用 C 语言和 POSIX 线程(pthread)创建一个简单的并发 HTTP 服务器。

大致服务过程如下:

那么如何实现呢?

1. 确定服务器需求

明确你的服务器需要支持哪些 HTTP 方法(GET, POST 等),以及预期的并发量。

2. 选择合适的编程语言和库

我们将使用 C 语言和 POSIX 线程(pthread)库来创建一个多线程的 HTTP 服务器。

3. 创建 socket

使用 socket() 系统调用创建一个 TCP socket。

cpp 复制代码
int serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if (serv_sock == -1) {
    perror("socket() error");
    exit(1);
}

4. 绑定地址和端口

使用 bind() 系统调用将 socket 绑定到一个地址和端口。

cpp 复制代码
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(PORT);

if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
    perror("bind() error");
    exit(1);
}

5. 监听连接

使用 listen() 系统调用开始监听连接。

cpp 复制代码
if (listen(serv_sock, 5) == -1) {
    perror("listen() error");
    exit(1);
}

6. 创建线程处理函数

编写一个函数,用于线程处理客户端连接。这个函数将解析 HTTP 请求,并返回一个简单的 HTTP 响应。

cpp 复制代码
void *handle_client(void *arg) {
    int clnt_sock = *(int *)arg;
    char request[1024];
    int read_len;

    // 读取 HTTP 请求
    read_len = read(clnt_sock, request, sizeof(request) - 1);
    if (read_len > 0) {
        request[read_len] = 0;
        printf("Received request: %s\n", request);

        // 发送 HTTP 响应
        char *response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><h1>Hello, World!</h1></body></html>";
        write(clnt_sock, response, strlen(response));
    }

    close(clnt_sock);
    return NULL;
}

7. 接受连接并创建线程

使用 accept() 系统调用接受客户端连接,并为每个连接创建一个新的线程。

cpp 复制代码
while (1) {
    struct sockaddr_in clnt_addr;
    socklen_t clnt_addr_size = sizeof(clnt_addr);
    int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

    if (clnt_sock == -1) {
        perror("accept() error");
        continue;
    }

    pthread_t t_id;
    if (pthread_create(&t_id, NULL, handle_client, (void *)&clnt_sock) != 0) {
        perror("pthread_create() error");
        continue;
    }

    pthread_detach(t_id); // 使线程分离,不需要等待其终止
}

8. 关闭服务器 socket

在服务器终止前,关闭服务器 socket。

cpp 复制代码
close(serv_sock);

9. 编译和运行

将上述代码保存为一个 .c 文件,例如 shttpd.c,然后使用以下命令编译:

cpp 复制代码
gcc -o shttpd shttpd.c -lpthread

运行服务器:

bash 复制代码
./shttpd

以上过程分析可以总结为一下uml图的过程:

注意事项

  • 上述代码仅用于演示目的,没有错误处理和资源清理。
  • 在生产环境中,应该添加适当的错误处理和日志记录。
  • 应确保服务器能够正确处理客户端断开连接的情况。
  • 考虑到安全性,可能需要实现更多的功能,如数据加密和身份验证。
  • 这个基本的示例仅支持 GET 方法,并且返回一个简单的 HTML 响应。实际应用中,你可能需要解析更多的 HTTP 请求头,支持其他 HTTP 方法,以及提供动态内容。

根据以上一个简单并发服务器的结构分析,我们知道了如何实现一个最简单属于自己的服务器,

好啦!到这里这篇文章就结束啦,关于实例代码中我写了很多注释,如果大家还有不懂得,可以评论区或者私信我都可以哦!! 感谢大家的阅读,我还会持续创造网络编程相关内容的,记得点点小爱心和关注哟!

相关推荐
tang777891 小时前
如何保护网络隐私?从理解代理IP开始
网络·tcp/ip·php
XH-hui1 小时前
【打靶日记】TheHackerLabs 之 THLPWN
linux·网络安全·thehackerlabs·thl
我是小超人-雨石花5 小时前
Jenkins&Robot Framework持续集成
运维·jenkins·ci
AA陈超6 小时前
ASC学习笔记0020:用于定义角色或Actor的默认属性值
c++·笔记·学习·ue5·虚幻引擎
捷米研发三部6 小时前
ProfiNet转Modbus TCP协议转换网关实现西门子PLC与工控机通讯在智能交通系统的应用案例
网络·网络协议
coderxiaohan6 小时前
【C++】仿函数 + 模板进阶
开发语言·c++
dreamtm1236 小时前
通俗理解 TCP 拥塞控制:像 “快递员看路况调速”,避免网络 “堵车”
网络·tcp/ip·php
wanhengidc7 小时前
云手机的软件核心是什么
运维·服务器·web安全·游戏·智能手机
芬加达7 小时前
jvm八股
运维·服务器·jvm
小兔薯了7 小时前
11. Linux firewall 防火墙管理
linux·运维·服务器