当使用websocket的时候,AUrl是 'ws://xxxx',协议应该是 http。 应用目录里面没有libcripto.dll。
Opened this issue · 9 comments
这时,仍然会尝试使用 https 创建httpclient,导致抛出‘没有可用的libcripto库’ 异常。
procedure TCrossWebSocketMgr.CreateHttpClis;
begin
inherited; // 这里直接通过父类调用 CreateHttpCli(https); 这里的 https 并没有与 AUrl里面的具体的协议进行验证。
CreateHttpCli(WS);
CreateHttpCli(WSS);
end;
实际调用的时候,是否应该根据创建websocketclient的时候,提供的 AUrl ws来只创建 http 的?
这是最近一次的更新改成这样的,目的是为了减少实际使用过程中的线程锁
倒是可以考虑再改进一下,增加一个是否使用ssl的参数,在确实不需要ssl的时候就不预先创建ssl对象了
ssl对象 最好是在客户open连接的时候,根据AUrl来设定,如果没有 wss 或者 https 的时候,就不需要创建。已经创建的,使用完成后,可能需要存放入一个队列里面,反复使用。
本来就是这么设计的,不过即便这样,只要动态创建,在多线程环境就需要加锁以保护队列对象
改成预先创建,后续直接读取无需修改,就不用再加锁了
如果这样设计,那么使用ws的时候,调用父类的方法,如果应用环境里面没有检索到 ssl 库, 就不创建,因为抛出异常会终止 ws 和 wss 的创建过程。
或者这样
procedure TCrossWebSocketMgr.CreateHttpClis;
begin
//inherited;
try
CreateHttpCli(HTTP);
CreateHttpCli(WS);
except
raise ...
end
try
CreateHttpCli(HTTPS);
CreateHttpCli(WSS);
except
raise ...
end
end;
分别创建, https 不影响 http的创建, 如果open的时候,使用了wss,但是没有ssl库,再抛出异常。
更新了一下代码,增加了一个Prepare方法,由用户自行调用预创建
后续使用的部分还是需要加锁,先这样吧,这个锁的性能损失应该可以接受
如果想去掉锁,按我提供的方式也是可以的。创建的时候,ssl只要不影响 ws 和 http 创建就可以。 没有ssl环境可以抛出异常,但是ws 已经创建好,用户想只使用ws,不用ssl,只要忽略这个异常就行。 后面用户如果open的时候,使用了wss,正常抛出异常,这时候如果他还用wss,那他就应该自己准备ssl库。
毕竟忽略一个提醒异常的代价要比使用锁的代价要低的多。
刚刚测试了一下, 如果不用锁,需要内部处理异常,不然websocket对象不会被创建。 可以根据是否有ssl的情况,返回创建的状态,表明是否支持 ssl。
__WebSocket := TCrossWebSocket.Create('ws://' + Self.FSrvIPv4 + ':' + Self.FSrvPort);
这里 __WebSocket 可以加一个公开属性,以区别是否可以支持 ssl。 但是不再抛出异常,因为异常会导致 __WebSocket 为 nil。
把wss 创建的这个异常内部直接忽略掉,如果用户使用open的时候使用的是wss,再获取一个httpclient ssl实例的时候,抛出找不到ssl的异常。如果用户不使用ssl,没有任何的影响,可以正常使用,这样ssl对象就不需要加锁。
procedure TCrossWebSocketMgr.CreateHttpClis;
begin
//inherited;
try
CreateHttpCli(HTTP);
CreateHttpCli(WS);
except
on E: Exception do
raise Exception.Create('Unable to create WebSocket client. ' + E.Message);
end;
try
CreateHttpCli(HTTPS);
CreateHttpCli(WSS);
except
//raise Exception.Create('SSL Websocket can not created.');
end;
end;
如果使用调用Prepare方法的方式,是否以后调用的时候,都要提前Prepare一下。 Demo 都要修改?
还是觉得 http 和 https 两种模式分别创建,只是在创建https之前,先检测ssl库是否存在,如果不存在,直接跳过创建 https 对象不再提醒也不抛异常打断程序。
如果用户使用https模式,只在Open的时候才抛出异常。
这样处理的好处,
- 不使用https的时候,用户没有任何的影响,他也不知道是否创建过https的对象。
- 可以去掉对 https的 ssl对象的锁。
- 使用https的用户,也不会影响,在Open的时候,他一样需要准备ssl库。
- 因为提前创建的时候不抛出异常,在开发的时候,使用 http 模式的时候, 不会因为在IDE里面每次都因为抛出内部异常,打断调试过程。
唯一的代价可能就是 使用 https,wss协议 的用户,创建了一个可能用不到的 http 对象。
处理的部分,在
Net.OpenSSL.pas 文件,
if (FCryptoLibHandle = 0) then
raise ESslInvalidLib.Create('没有可用的libcrypto库');
不再raise异常,另外增加一个 checkLibcrypto 库的方法。
预创建的时候,不调用 checklibcrypto 方法。并且在 if (FCryptoLibHandle = 0) then 直接返回一个 nil。
在用户 调用 Open 连接的时候, 检测 https 或者 wss 对象是否为 nil,如果是 nil 然后调用 checklibcrypto 方法, 如果check失败, raise 没有库异常。
这样可以去掉ssl对象的锁。同时,ssl是否存在不影响 http 非加密对象创建,对非加密模式使用时透明的。
这样不需要prepare。