[高并发网络通信架构]实现tcp的高并发服务端

打印 上一主题 下一主题

主题 1026|帖子 1026|积分 3078

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
想要实现tcp的高并发服务端,我们就必须知道什么是高并发,是不是只有服务端才会有,以及我们应该怎样去办理这种情况。相信看完这篇,你会有新的理解。
首先我们来办理第一个问题:什么是高并发?
高并发指的是体系能够同时处置惩罚大量并发请求的本事。在盘算机科学中,"并发"是指在同一时间段内有多个使命在实验,而"高并发"则体现体系在面对大量并发请求时能够保持稳固、可靠地运行。
高并发通常出现在需要处置惩罚大量用户请求的体系中,比方网络服务器、电子商务平台、交际媒体应用等。这些体系需要能够同时处置惩罚大量的用户请求和数据交互操纵,而不因为请求量过多而导致性能降落或体系崩溃。
举个栗子吧,寒假的末了,你看着一个字没动的作业,默默地喊来了你的家人帮你一起写作业,这就是“高并发”,几个人同时去完成你的寒假作业。相信你们肯定在寒假的开始就已经完成了作业。
2.是不是只有服务端才会有高并发?
不完全是。固然高并发通常更多地与服务器端体系相干,因为服务器需要同时处置惩罚大量的客户端请求,但客户端也可能面对高并发的情况。以下是一些客户端可能碰面对高并发的情况:
1. **移动应用步伐**:在移动应用步伐中,假如有大量用户同时使用应用、发送请求大概举行数据交互,客户端也可能面对高并发的情况。
2. **Web 欣赏器**:当用户打开大量标签页面,每个页面都要发送请求加载内容时,欣赏器也需要处置惩罚大量并发请求。
3. **物联网设备**:在物联网场景下,大量设备同时连接到互联网,向服务器发送数据或吸收指令,也可能导致客户端的高并发情况。
4. **大规模数据处置惩罚客户端**:在数据分析、机器学习等范畴,客户端可能需要处置惩罚大量的数据盘算使命,也碰面对高并发的情况。
固然客户端面对的高并发情况通常不像服务器端那么复杂,但仍旧需要考虑如何有效地管理和处置惩罚大量的并发请求,以确保客户端体系的稳固性和性能。在客户端中,通常采用异步处置惩罚、缓存、并发控制等技术来应对高并发情况,提高体系的响应速率和并发处置惩罚本事。
3,我们应该怎么办理呢
实现高并发的关键是有效地管理和分配体系资源,以确保每个请求都能够得到及时响应。以下是一些常见的实现高并发的策略和技术:
1. 负载均衡:将请求分发到多个服务器上,以平衡服务器的负载,防止单台服务器过载。
2. 水平扩展:通过增长服务器数量来增长体系处置惩罚并发请求的本事,以适应不停增长的请求量。
3. 异步处置惩罚:使用非壅闭的 I/O 操纵和事件驱动的编程模子,使体系能够同时处置惩罚多个请求,而不需要等待每个请求的完成。
4. 缓存:将常常访问的数据缓存在内存中,减少数据库访问的频率,提高体系的响应速率。
5. 数据库优化:使用符合的数据库索引、分区等技术,提高数据库的读写性能和并发处置惩罚本事。
6. 限流和排队:通过限制每个用户或每秒钟的请求数量,防止体系被过多请求压垮,同时使用队列来缓冲请求,确保每个请求都得随处置惩罚。
高并发是当代体系操持中的紧张考虑因素之一。通过公道的架构操持和技术选型,可以提高体系的并发处置惩罚本事,保证体系的稳固性和性能。
我们今天就通过编程的方式去办理并发情况。
刚才都是水字数,重点来喽!!!!
IO多路复用
介绍:


I/O多路复用(IO Multiplexing)是一种并发编程技术,用于同时监视多个I/O事件并选择停当的事件举行处置惩罚。它可以通过一个线程或进程同时处置惩罚多个I/O操纵,而不需要为每个I/O操纵创建一个独立的线程或进程。I/O多路复用可以提高体系的并发性能,减少资源的斲丧。
在传统的编程模子中,每个I/O操纵通常都需要一个独立的线程或进程来处置惩罚。这种方式在面对大量的并发连接时,会导致体系资源的浪费和性能降落。而I/O多路复用通过使用一种事件驱动的方式,可以同时监视多个I/O事件,只有当有事件停其时才举行相应的处置惩罚,从而提高了体系的并发性能。
常见的I/O多路复用函数包括"select"、"poll"、"epoll"等。这些函数可以同时监视多个文件描述符的状态,并确定哪些文件描述符已经准备好可举行相应的读取、写入或异常处置惩罚。通过使用这些函数,可以制止为每个I/O操纵创建一个独立的线程或进程,从而减少了体系资源的斲丧。
I/O多路复用的工作原理是通过一个事件循环来监视多个I/O事件。当有一个或多个事件停其时,事件循环会通知步伐举行相应的处置惩罚。这种方式可以大大提高体系的并发性能,减少了线程或进程的切换开销。
总结
I/O多路复用是一种并发编程技术,用于同时监视多个I/O事件并选择停当的事件举行处置惩罚。它可以提高体系的并发性能,减少资源的斲丧。通过使用I/O多路复用函数,可以制止为每个I/O操纵创建一个独立的线程或进程,从而提高体系的服从。
接下来,通过这三个函数的学习进一步了解io的多路复用。
1,select模子

`select` 模子是一种 I/O 多路复用技术,用于实现同时监听多个文件描述符(sockets)的读写事件,从而实现高效的事件驱动编程。在网络编程中,`select` 函数通常用于同时监控多个套接字(sockets)上的 I/O 事件,当此中任何一个套接字准备好举行读取或写入时,`select` 函数就会通知应用步伐。
以下是 `select` 模子的一些特点和用法:
1. **多路复用**:`select` 允许步伐同时监视多个文件描述符,一旦此中任何一个文件描述符停当(可读、可写等),就通知应用步伐举行相应的处置惩罚。
2. **壅闭调用**:`select` 函数通常是壅闭的,即在调用 `select` 函数后,步伐会不停等待,直到有文件描述符停当大概超时才返回。
3. **可设置超时时间**:除了等待文件描述符停当外,`select` 函数还可以设置超时时间,凌驾指定时间后纵然没有文件描述符停当也会返回。
4. **跨平台支持**:`select` 是一种比力古老但跨平台支持良好的 I/O 多路复用技术,在大多数主流操纵体系上都有对应的实现。
5. **易于使用**:相对于其他 I/O 多路复用技术如 `epoll` 和 `kqueue`,`select` 的接口简单,易于使用,适合一些简单的网络编程场景。
只管 `select` 在某些方面具有肯定的局限性,比方性能不如 `epoll`,但在某些场景下仍旧具有肯定的上风,特别是在需要跨平台支持大概需要简单易用的情况下。在实际应用中,可以根据详细需求和场景选择符合的 I/O 多路复用技术来提高步伐的性能和并发本事。
我们先看函数
  1. select头文件:<sys/select.h>
  2. 函数原型:int select(int nfds,
  3.                     fd_set *readfds,
  4.                     fd_set *writefds,
  5.                     fd_set *exceptfds,
  6.                     struct timeval *timeout);
  7. 参数:
  8. nfds:监视的文件描述符集合中所有文件描述符的范围,
  9.       即待监视的文件描述符中最大的文件描述符值加1。
  10. readfds:指向 fd_set 结构体的指针,
  11.          用于监视是否有数据可以读取的文件描述符集合。
  12. writefds:指向 fd_set 结构体的指针,
  13.           用于监视是否可以写入数据到文件描述符的集合。
  14. exceptfds:指向 fd_set 结构体的指针,用于监视异常条件的文件描述符集合。
  15. timeout:指定 select 的超时时间,如果为 NULL 则表示一直阻塞,
  16.         直到有文件描述符就绪;如果设置为具体的时间值,则表示超时时间。
  17. fd_set 是一个位向量,用于表示文件描述符的集合,其定义如下:
  18. typedef struct {
  19.     unsigned long fds_bits[FD_SETSIZE / (8 * sizeof(unsigned long))];
  20. } fd_set;//如果有兴趣,下去可以了解一下
  21. 在调用 select 函数后,会在 readfds、writefds 和 exceptfds 中设置相应文件描述符的状态,
  22. 以指示哪些文件描述符已经就绪。select 函数会返回就绪文件描述符的数量,或者在超时情况下返回0。
  23. 注意:的是,select 函数在一些操作系统上有文件描述符数的限制,通常为 1024,
  24. 超过这个限制可能会导致不可预测的行为。因此,在使用 select 函数时需要注意文件描述符数量的限制。
复制代码
服务端代码

客户端代码

我们这里通过select实现了一个服务端和多个客户端之间的通信,简单的运行一下喽。

我相信这个函数大家肯定有了了解,那我们继续第二个喽
2,poll
`poll` 模子是一种基于事件驱动的 I/O 多路复用模子,用于实现高效的并发网络编程。它通过调用体系调用 `poll` 来同时监听多个文件描述符的可读、可写等事件,并在事件停其时举行相应的处置惩罚。
在 `poll` 模子中,通过创建一个 `pollfd` 结构体数组来生存要监视的文件描述符和感爱好的事件。每个 `pollfd` 结构体描述了一个文件描述符及其关注的事件类型。在调用 `poll` 函数时,将该数组通报给 `poll` 函数,并设置超时时间。
`poll` 函数将会壅闭步伐,直到以下三种情况之一发生:
1. 监视的文件描述符中的至少一个事件发生(如可读、可写等)。
2. 超时时间到达。
3. 出错发生。
当 `poll` 函数返回时,可以通过遍历 `pollfd` 结构体数组来检查哪些文件描述符的事件已经停当。根据事件类型,可以采取相应的操纵,比如读取数据、发送数据等。
`poll` 模子相对于传统的壅闭式 I/O 或使用多线程/多进程的并发模子具有以下长处:
1. 单线程:使用 `poll` 模子可以在单个线程中处置惩罚多个并发连接,而无需创建多个线程或进程。
2. 简单:相对于使用复杂的线程同步和互斥机制,`poll` 模子编程更加简单易懂。
3. 高效:可以同时监视多个文件描述符,实现高效的并发处置惩罚。
然而,需要留意的是,在大规模并发的情况下,`poll` 模子可能会遇到性能瓶颈。因此,在这种情况下,可以考虑使用更高级的多路复用机制,如 `epoll` 或 `kqueue`,以提高性能和扩展性。
总结来说,`poll` 模子是一种基于事件驱动的 I/O 多路复用模子,通过调用 `poll` 函数并遍历 `pollfd` 结构体数组来实现对多个文件描述符的并发监听和处置惩罚。它是实现高效并发网络编程的一种常见选择。
与select相比poll突破了文件描述符的限制
  1. poll
  2. 头文件:#include <poll.h>
  3. 函数原型:int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  4. 参数fds 是一个指向 pollfd 结构体数组的指针
  5.         nfds 表示 fds 数组中的文件描述符数量
  6.         timeout 表示超时时间。
  7. pollfd 结构体用于描述要被监视的文件描述符及其关注的事件类型。其定义如下:
  8. struct pollfd {
  9.     int fd;         /* 文件描述符 */
  10.     short events;   /* 待监视的事件 */
  11.     short revents;  /* 实际发生的事件 */
  12. };
  13. events 字段表示要监视的事件类型,可以是以下值之一或它们的组合:
  14. POLLIN:表示可读事件。
  15. POLLOUT:表示可写事件。
  16. POLLPRI:表示紧急数据可读事件。
  17. POLLERR:表示错误事件。
  18. POLLHUP:表示挂起事件。
  19. POLLNVAL:表示无效请求事件。
  20. revents 字段表示实际发生的事件类型,由内核填充。
  21. nfds 参数表示 fds 数组中的文件描述符数量。
  22.      在 Linux 系统中,nfds 的取值范围是从 0 到 INT_MAX。
  23. timeout 参数指定超时时间,以毫秒为单位。
  24. 如果 timeout 为负数,则 poll() 将会一直阻塞,直到有事件发生;
  25. 如果 timeout 为 0,则 poll() 在检查文件描述符后立即返回,不等待任何事件;
  26. 如果 timeout 大于 0,则 poll() 最多等待 timeout 毫秒后返回,无论是否有事件发生。
  27. 在调用 poll() 函数后,如果有事件发生,则会修改 revents 字段以指示实际发生的事件类型。
  28. 我们可以遍历 fds 数组来查找哪些文件描述符的事件已经就绪。
  29. poll() 函数返回值表示有多少个文件描述符就绪。如果 poll() 超时,则返回值为 0;
  30. 如果发生错误,则返回 -1 并设置 errno 变量来指示错误类型。
  31. 总之,poll() 是一个用于实现 I/O 多路复用的系统调用,
  32. 在 Linux 系统中广泛应用于高效的网络编程。
复制代码
3.epoll
epoll(事件轮询)是Linux操纵体系提供的一种高性能I/O多路复用机制,在处置惩罚大规模的并发连接时具有良好的服从和可扩展性。它通过使用内核的事件通知机制来同时监视和处置惩罚多个文件描述符的事件,大大减少了轮询的开销,提高了体系的并发性能。
epoll就的底层是一颗红黑树,而select和poll则都为顺序表,所以与传统的select和poll函数相比,epoll在处置惩罚大规模并发连接时具有更高的服从。
  1. 在使用 epoll 模型时,常用的函数包括 `epoll_create`、`epoll_ctl` 和 `epoll_wait`。
  2. 下面我会逐一介绍这些函数的作用和用法。
  3. 1. `int epoll_create(int size)`
  4.    - 创建一个 epoll 实例。
  5.    - 参数 `size` 指定了 epoll 实例中能够监控的文件描述符的数量上限,
  6.      所以这个参数在大多数情况下可以被忽略(传入大于 0 的值即可)。
  7. 2. `int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)`
  8.    - 控制 epoll 实例中的事件。
  9.    - `epfd` 是 epoll 实例的文件描述符。
  10.    - `op` 可以是以下值之一:
  11.      - `EPOLL_CTL_ADD`:向 epoll 实例中添加要监控的文件描述符。
  12.      - `EPOLL_CTL_MOD`:修改 epoll 实例中的文件描述符的监控事件。
  13.      - `EPOLL_CTL_DEL`:从 epoll 实例中移除不再需要监控的文件描述符。
  14.    - `fd` 是要操作的文件描述符。
  15.    - `event` 是一个指向 `struct epoll_event` 结构体的指针,该结构体描述了要监听的事件类型。
  16. 3. `int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)`
  17.    - 等待 epoll 实例中的事件发生。
  18.    - `epfd` 是 epoll 实例的文件描述符。
  19.    - `events` 是一个数组,用于存储发生的事件。
  20.    - `maxevents` 是 `events` 数组的大小,表示最多能够存储多少个事件。
  21.    - `timeout` 指定等待事件发生的超时时间,单位为毫秒。传入 `-1` 表示无限等待直到有事件发生。
  22. 这些函数是使用 epoll 模型时最常用的函数,通过它们可以创建 epoll 实例、控制文件描述符的监听事件以及等待事件的发生。希望这些信息能够帮助你更好地理解和使用 epoll 模型。如果还有其他问题,欢迎继续提问。
复制代码
我们直接看代码吧

就聊到这里吧,我们下期再见喽!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宝塔山

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表