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

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 方法,以及提供动态内容。

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

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

相关推荐
UIU11439 分钟前
递归算法与汉诺塔
c++·学习·算法·c#·递归
Fruit_Caller1 小时前
static
开发语言·c++
律宏阔6 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔6 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴6 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千6 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei376 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei376 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei376 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
judezh6 小时前
api 容器一直 unhealthy?我把一个 Agent 运行时的健康检查逐条拆了,查出四个问题
运维·docker