SSL实现必须读取整条记录,哪怕select返回了一个字节可读,那么ssl也要读取整个记录,这种基于纪录的读写方式就是为了正确的加密和解密。因此如果用select模型的话可能会出现一些莫名其妙的问题,事实上也正是ssl消息需要加密解密从而需要整个消息整个消息读写才使得ssl协议的行为和tcp的有了少有的不一致。
1>tcp的特点是流式传输,流式的特点就是没有消息边界,一个连接就是一个流,需要应用程序自己去划分自己的数据,举个例子就是一端写入x个字节,对端可能读出y个字节,具体多少要看网络状况和窗口情况,tcp在这一点上是相当复杂的,应用程序的发送只是简单的将数据放入tcp的发送缓冲区,而接收只是简单的从接收缓冲区中取回数据。
2>反观udp就不是这样子,udp是基于数据报的,就是说不能分段,一端写入多少另一端就读出多少,当然也可能永远收不到,也可能乱序等等。
3>现在看看ssl,它看起来好像是结合了tcp和udp的特点,它是有连接的,必须可靠传输并且按照顺序收发,但是却不是流式的,每次 (一个ssl纪录有一个固定大小的头部[5字节],该头部指示了消息类型,ssl版本号以及消息长度),首先需要读出一个ssl消息头部,接下来就要在该头部的消息长度字段的指导下进行消息体的读取,而且必须读取完整个完整消息之后才能返回成功,否则均返回失败,并且什么都不做,ssl读操作中,带有头的消息是read的最小单位。
因此,select机制可以监听到最后一个ssl消息的头部,但是若系统缓存还没有收到完整ssl数据,或软件没有一次性读完,剩余的数据将不会再触发select,导致无法读完整。
解决方法就是使用SSL_pending机制判断是否有数据接收,这个函数可以检测目标SSL中到底有多少可读数据。
SSL数据接收不要用select
最新推荐文章于 2021-12-01 20:34:50 发布