从零构建通讯器--5.8 ET、LT深入分析及测试,服务器设计、粘包解决

(1)ET,LT模式深入分析及测试

1)ET:边缘触发/告诉模式,这个事件通知只会出现一次;
普遍认为ET比LT效率高一些,但是 ET编程难度比LT大一些,ET模式下,如果没有数据可接收,则recv会返回-1;egain表示再触发一次再为-1时,就触发break,防止第一次出现-1只是一个提示时就不需要退出
在这里插入图片描述
若客户端断开
在这里插入图片描述
服务器端设置成若n=0,break
在这里插入图片描述
2)LT:水平触发/低速模式,这个事件没处理完,就会被 一直触发;
设置成LT模式,epollet设置成0
在这里插入图片描述
LT测试代码
在这里插入图片描述

LT效果
在这里插入图片描述
LT简单多了
②思考:
1)为什么ET模式事件只触发一次[事件被扔到双向链表中一次,被epoll_wait取出后就干掉]
2)LT模式事件会触发多次呢?[事件如果没有处理完,那么事件会被多次往双向链表中扔]
③如何选择ET,还是LT
1)//如果收发数据包有固定格式【后续会讲】,那么老师建议采取LT:编程简单,清晰,写好了效率不见得低;
//老师准备本项目中采用LT这种方法【固定格式的数据收发方式来写我们的项目】
2)如果收发数据包没有固定格式,可以考虑采用ET模式(官方采用ET模式);

(2)我们的服务器设计
(2.1)服务器设计原则总述
我们写的是:通用的服务框架:将来,稍加改造甚至不用改造就可以把它直接应用在很多的具体开发工作中;
我们的工作重点就可以聚焦在业务逻辑上; 相当于你自带框架【自带源码】入职;甚至你可以挑战高级程序员/主程序这种职业;
(2.2)收发包格式问题提出
第一条命令出拳【1abc2】,第二条加血【1def2|30】;
命令:1abc21def2|30
(2.3)TCP粘包、缺包
①tcp粘包问题
client发送abc,def,hij,三个数据包发出去;
②a)客户端粘包现象(没必要解决客户端粘包问题)
客户端因为有一个Nagle优化算法;(100到200毫秒内)
//send(“abc”); write()也可以
//send(“def”);
//send(“hij”);
因为Nagle算法存在的,这三个数据包被Nagle优化算法直接合并一个数据包发送出去;这就属于客户端粘包;
如果你关闭Nagle优化算法,那么你调用几次send()就发送出去几个包;那客户端的粘包问题就解决了;
③b)服务器端粘包现象
不管你客户端是否粘包,服务器端都存在粘包的问题:就算你客户端不粘包,但是,仍然避免不了服务器端粘包的问题,针对该TCP连接收数据缓冲中【abcdefhij】;你再次recv一次,就可能拿到了全部的“abcdefhij”,这就叫服务器端的 粘包;
(2.4)TCP粘包、缺包解决:面试服务器岗位经常考,没听说过粘包或者不会解决TCP粘包这个问题,那么会立即被pass;
1)方法:如何解决拆包问题:给收发的数据包定义一个统一的格式[规则];c/s都按照这个格式来,就能够解决粘包问题;
2)具体:
①包格式: 包头+包体 的格式;其中 包头 是固定长度【10字节】,在包头中,有一个成员变量会记录整个包【包头+包体】的长度;
②这样的话,先收包头,从包头中,我知道了整个包的长度,然后 用整个包的长度 - 10个字节 = 包体的长度。
③我再收 “包体的长度”这么多的字节; 收满了包体的长度字节数,我就认为,一个完整的数据包【包头+包体】收完;
3)收包总结:
//(1)先收固定长度包头 10字节;
//(2)收满后,根据包头中的内容,计算出包体的长度:整个长度-10
//(3)我再收包体长度这么多的数据,收完了,一个包就完整了;
//我们就认为受到了一个完整的数据包;从而解决了粘包的问题;
在这里插入图片描述

补充:
官方的nginx的代码主要是用来处理web服务器【一种专用的服务器】,代码写的很庞杂;
不太适合咱们这种固定数据格式【包头+包体】的服务器【通用性强的服务器,可以应用于各种领域】

web服务器接受各种格式的数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一门linux下c++通讯架构实战课程,针对c/c++语言已经掌握的很熟并希望进一步深造以将来用c++在linux下从事网络通讯领域/网络服务器的开发和架构工作。这门课程学习难度颇高但也有着极其优渥的薪水(最少30K月薪,最高可达60-80K月薪),这门课程,会先从nginx源码的分析和讲解开始,逐步开始书写属于自己的高性能服务器框架代码,完善个人代码库,这些,将会是您日后能取得高薪的重要筹码。本课程原计划带着大家逐行写代码,但因为代码实在过于复杂和精细,带着写代码可能会造成每节课至少要4~5小时的超长时间,所以老师会在课前先写好代码,主要的时间花费在逐行讲解这些代码上,这一点望同学们周知。如果你觉得非要老师领着写代码才行的话,老师会觉得你当前可能学习本门课程会比较吃力,请不要购买本课程,以免听不懂课程并给老师差评,差评也会非常影响老师课程的销售并造成其他同学的误解。 这门课程要求您具备下面的技能:(1)对c/c++语言掌握的非常熟练,语言本身已经不是继续学习的障碍,并不要求您一定熟悉网络或者linux;(2)对网络通讯架构领域有兴趣、勇于挑战这个高难度的开发领域并期望用大量的付出换取高薪;在这门课程中,实现了一个完整的项目,其中包括通讯框架和业务逻辑框架,浓缩总结起来包括如下几点:(1)项目本身是一个极完整的多线程高并发的服务器程序;(2)按照包头包体格式正确的接收客户端发送过来的数据包, 完美解决收包时的数据粘包问题;(3)根据收到的包的不同来执行不同的业务处理逻辑;(4)把业务处理产生的结果数据包正确返回给客户端;本项目用到的主要开发技术和特色包括:(1)epoll高并发通讯技术,用到的触发模式是epoll中的水平触发模式【LT】;(2)自己写了一套线程池来处理业务逻辑,调用适当的业务逻辑处理函数处理业务并返回给客户端处理结果;(3)线程之间的同步技术包括互斥量,信号量等等;(4)连接池中连接的延迟回收技术,这是整个项目中的精华技术,极大程度上消除诸多导致服务器程序工作不稳定的因素;(5)专门处理数据发送的一整套数据发送逻辑以及对应的发送线程;(6)其他次要技术,包括信号、日志打印、fork()子进程、守护进程等等;
以下是一个基本的C# Socket通讯服务器示例,其中包含了同步接收和解决粘包的处理逻辑: ```csharp using System; using System.Net; using System.Net.Sockets; using System.Text; public class Server { private static Socket listener; public static void Main(string[] args) { StartServer(); } public static void StartServer() { // 创建IP地址和端口号 IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); int port = 12345; // 创建监听器 listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listener.Bind(new IPEndPoint(ipAddress, port)); listener.Listen(100); Console.WriteLine("Server started and waiting for clients..."); while (true) { // 等待客户端连接 Socket client = listener.Accept(); Console.WriteLine("Client connected: " + client.RemoteEndPoint.ToString()); // 处理客户端请求 byte[] buffer = new byte[1024]; int bytesReceived = client.Receive(buffer); string message = Encoding.ASCII.GetString(buffer, 0, bytesReceived); // 解决粘包 string[] messages = message.Split(new string[] { "<EOF>" }, StringSplitOptions.RemoveEmptyEntries); foreach (string m in messages) { Console.WriteLine("Received message: " + m); } // 发送响应 byte[] response = Encoding.ASCII.GetBytes("Server response"); client.Send(response); // 关闭连接 client.Shutdown(SocketShutdown.Both); client.Close(); } } } ``` 在这个示例中,我们使用了一个 `Split` 方法来将从客户端接收到的消息分割成多个消息。这个方法使用了 `<EOF>` 字符串作为分隔符,因此客户端发送的消息必须以该字符串结尾。如果不是以该字符串结尾,则会认为是粘包,并会将多个消息合并成一个。在实际应用中,可以根据具体的需求选择不同的分隔符或者使用其他方式来解决粘包问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值