| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> 《ZLToolKit源码学习笔记》(23)网络模块之UdpServer -> 正文阅读 |
|
[网络协议]《ZLToolKit源码学习笔记》(23)网络模块之UdpServer |
系列文章目录《ZLToolKit源码学习笔记》(1)VS2019源码编译 《ZLToolKit源码学习笔记》(2)工具模块之日志功能分析 《ZLToolKit源码学习笔记》(3)工具模块之终端命令解析 《ZLToolKit源码学习笔记》(4)工具模块之消息广播器 《ZLToolKit源码学习笔记》(6)线程模块之整体框架概述 《ZLToolKit源码学习笔记》(7)线程模块之线程池组件:任务队列与线程组 《ZLToolKit源码学习笔记》(8)线程模块之线程负载计算器 《ZLToolKit源码学习笔记》(9)线程模块之任务执行器 《ZLToolKit源码学习笔记》(11)线程模块之工作线程池WorkThreadPool 《ZLToolKit源码学习笔记》(12)事件轮询模块之整体框架概述 《ZLToolKit源码学习笔记》(13)事件轮询模块之管道的简单封装 《ZLToolKit源码学习笔记》(14)事件轮询模块之定时器 《ZLToolKit源码学习笔记》(15)事件轮询模块之事件轮询器EventPoller 《ZLToolKit源码学习笔记》(16)网络模块之整体框架概述 《ZLToolKit源码学习笔记》(17)网络模块之基础接口封装类SockUtil 《ZLToolKit源码学习笔记》(18)网络模块之Buffer缓存 《ZLToolKit源码学习笔记》(19)网络模块之套接字封装 《ZLToolKit源码学习笔记》(20)网络模块之TcpServer 《ZLToolKit源码学习笔记》(21)网络模块之TcpClient 《ZLToolKit源码学习笔记》(22)网络模块之TcpSession 《ZLToolKit源码学习笔记》(23)网络模块之UdpServer(本文) ?前言本节学习ZLToolKit的UDP服务器封装。 目录1.4、UDP服务器如何实现监听socket与会话socket的分离 2.2、处理server fd多次收到同一client连接发送的数据 一、概述1.1、类图Server类作为基类,将服务器和EventPoller进行了关联。 1.2、网络模型服务器模型:与TcpServer类似,使用多线程+epoll (select),一个Server?fd + 多个epoll实例 每一个线程都创建了一个epoll实例,并以ET边沿触发模式监听同一个Server fd的读事件,使用 当有客户端发送数据到Server fd时,针对该客户端创建一个新的会话(新的文件描述符,同样使用ET边沿触发),后续该客户端的数据将不会再发送到Server fd。 UdpServer与TcpServer流程基本一致,以下仅简单分析下。 1.3、如何实现连接的负载均衡ZLToolKit使用多线程技术,每一个线程中都创建了自己私有的epoll实例(非linux系统使用select,不做分析),并以ET模式监听同一个server fd的读(UDP还有写)事件,这种方式我们知道是有惊群效应的,所以需要给每一个fd事件加上EPOLLEXCLUSIVE标志位(内核4.5+支持)来避免惊群。后续客户端的fd将均匀的分配到这多个线程中处理。 每一个线程都能接受新的客户端连接,并且管理一部分已有的客户端连接。 1.4、UDP服务器如何实现监听socket与会话socket的分离对于TCP服务器,由于TCP是有连接的,server fd使用listen系统调用,只用来处理client连接过程,然后使用accept为客户端连接分配一个新的client fd,后续针对该客户端的会话数据读写就和server fd没关系了。说白了,就是TCP四元组在这个过程中就唯一确定并缓存下来了,后续该客户端发送的数据,通过查询四元组,就可以唯一匹配到对应的client fd上。 可以看到,TCP服务器的监听socket与会话socket天然就是分开的,每一个客户端都有独立的client fd。 但是对于UDP服务器,由于它是无连接的,不用经过三次握手的过程就可以直接发送数据,一个UDP socket没有服务器客户端之分,对于服务器来说,一个socket就可以接受所有的客户端数据,这必然导致数据的处理变得非常复杂,比如,如何区分不同的客户端,如何高效且安全的在多线程下处理客户端数据等。 我们看下ZLToolKit是如何解决的。在TCP服务器中,有一个只处理客户端连接的socket(listen fd),然后每一个客户端都有自己的client socket。接受新连接和客户端的数据交互是分开的。 而UDP中,这两者是混杂在一起的。所以,我们可以模拟TCP,当server fd对应的socket上收到某个客户端发来的数据后,不通过server socket去响应该客户端,而是新建立一个socket,该socket与server socket绑定相同的IP和端口(通过SO_REUSEADDR实现),并且,为了确定唯一的四元组,在该socket上调用connect API与客户端进行了关联。这样,后续客户端发送的数据将被转发到这个新的socket上来处理。 当然,使用这种方式实现的UDP服务器还有很多弊端,比如客户端程序必须绑定固定的IP和端口,不然每次客户端都随机使用一个端口来发送数据,会导致服务器的四元组失效。更详细的介绍可以参见以下文章: 二、代码实现2.1、新socket的创建过程?createSession函数中,以下三行代码就是创建新socket的过程,新socket与server socket绑定相同的IP和端口,然后再connect到peer客户端,确定四元组。
2.2、处理server fd多次收到同一client连接发送的数据一般仅在一个新的客户端连接第一次发送数据时,data才会在server fd上被接收到,其它时间都会发送到已创建的新socket上。但这不是绝对的,所以服务器还需要处理多次收到同一client发送数据的情况。
server fd接收到客户端数据时,获取已存在的会话或者创建一个新的会话(创建新的sokcet的过程),该会话将处理后续所有这个客户端的数据,server fd将不会再收到该客户端的数据。 这里有个注意点,在创建新的会话时,可能客户端已经发送了多条数据了,这多次数据都发送到了server fd上,server fd在处理第一条数据时,虽然已经创建新的会话处理后续客户端发送的数据,但是已经发出来的数据还是会在server fd上处理,所以,此处才需要查找该客户端对应的已存在会话,让其来处理这部分已经发送出来的数据。 为什么要判断是不是当前线程呢?从上边的描述可以看到,server fd可能收到多次客户端发来的数据,在第一条数据时,我们已经创建了一个新的会话socket,这个会话socket可能会被放在其它poller线程去监听,所以,server fd上后续的数据,就需要转移到这个poller线程中,确保同一个client发送过来的数据始终在一个线程中处理。但实际上,ZLToolkit的实现中,将新的会话socket还是放在当前线程中处理了,并没有放在其它线程。以下代码可以看到,新socket使用的还是server socket的poller线程。
而在TCP服务器的实现中,是选择了负载最轻的线程来管理新的会话socket,所以存在socket被其它线程管理的情况,参见以下代码:
2.3、新socket分配到其它线程可能存在的问题createSession函数中,以下代码本人觉得可能存在问题。
如果新的会话socket分配在其它线程,将使用异步任务执行,假设会话在还没有创建成功前,当前server线程再次收到该客户端数据,在_session_map中没有查询到对应的会话,就会再次触发创建新会话的操作。 目前的实现新会话socket还是在当前线程,所以不存在上述问题。 ? |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 11:39:26- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |