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

embedded/2024/10/19 23:34:15/

 16b9d0dfc990426e968798e2f5a7628b.png

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

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

03d6d5d7168e4ccb946ff0532d6eb8b9.gif               

  16b9d0dfc990426e968798e2f5a7628b.png如何创建高并发服务器

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

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

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

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

大致服务过程如下:
c943d7d2e15e42c6b86390b9711307e6.png

那么如何实现呢? 

1. 确定服务器需求

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

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

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

3. 创建 socket

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

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

4. 绑定地址和端口

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

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() 系统调用开始监听连接。

if (listen(serv_sock, 5) == -1) {perror("listen() error");exit(1);
}

6. 创建线程处理函数

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

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() 系统调用接受客户端连接,并为每个连接创建一个新的线程。

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。

close(serv_sock);

9. 编译和运行

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

gcc -o shttpd shttpd.c -lpthread

运行服务器

./shttpd

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

30f2bdaa7e9c4b6ebc09e244afe3fccb.jpeg 

注意事项

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

19d9a30b34cf4eedad4b1aff21578dbd.jpeg

 

 

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

 

 

 

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

 


http://www.ppmy.cn/embedded/3897.html

相关文章

每日三个JAVA经典面试题(四十二)

1.Java中的线程池如何帮助优化性能&#xff1f; Java中的线程池是一种重要的并发编程工具&#xff0c;它可以帮助优化性能的方式有以下几点&#xff1a; 资源管理&#xff1a;线程池可以管理并重用线程&#xff0c;而不是为每个任务都创建一个新的线程。这减少了线程创建和销毁…

Vue.js------Vue组件基础

能够理解Vue组件概念和作用能够掌握封装创建组件能力能够使用组件之间通信能够完成todo案例 一.Vue组件创建和使用 1.折叠面板-实现多个 创建一个文件夹demo 具体步骤请参考vue.js---vue基础 ⚫ 解决方案: 采用vue提供的单.vue文件-组件方式来封装一套然后复用 在component…

weblogic JSP action的配置

action(如xxx.do&#xff09;可以在Java文件中通过注解的方式配置&#xff0c;也可以在web.xml中进行配置 在java文件中配置的场合 WebServlet(xxxx.do) 并实现支持的方法&#xff1a;doGet或doPost等 或者 WebServlet(xxxx.do) 并实现service方法 所有method的处理方法都会…

mysql面试题七(集群)

目录 1.mySQL 中有哪些常见日志 错误日志&#xff08;Error Log&#xff09; 二进制日志&#xff08;Binary Log, Binlog&#xff09; 重做日志&#xff08;Redo Log&#xff09; 回滚日志&#xff08;Undo Log&#xff09; 慢查询日志&#xff08;Slow Query Log&#xf…

【面试八股总结】排序算法(二)

参考资料 &#xff1a;阿秀 一、堆排序 堆排序基本思想是先把数组构造成一个大顶堆(父亲节点大于其子节点)&#xff0c;然后把堆顶(数组最大值&#xff0c;数组第一个元素)和数组最后一个元素交换&#xff0c;这样就把最大值放到了数组最后边。把数组长度n-1,再进行构造堆把剩…

设计模式之观察者模式(下)

3&#xff09;JDK对观察者模式的支持 1.概述 在JDK的java.util包中&#xff0c;提供了Observable类以及Observer接口&#xff0c;它们构成了JDK对观察者模式的支持。 2.Observer接口 在java.util.Observer接口中只声明一个方法&#xff0c;它充当抽象观察者。 void update…

安全中级-环境安装(手动nginx以及自动安装php,mysql)

为了方便大家跟bilibili课程&#xff0c;出了第一节环境 bilibili搜凌晨五点的星可以观看相关的教程 一、环境 ubentu 二、nginx手动安装 2.1第一步 wget https://nginx.org/download/nginx-1.24.0.tar.gz 2.2下载好安装包以后解压 tar -zxvf nginx-1.21.6.tar.gz2.3安…

详解Qt中的JSON操作

JSON&#xff08;JavaScript Object Notation&#xff09;作为一种轻量级的数据交换格式&#xff0c;因其简洁的结构、易读性以及与多种编程语言的良好兼容性&#xff0c;在现代Web服务、API交互以及数据持久化场景中得到了广泛应用。Qt作为一款功能强大的跨平台应用开发框架&a…