Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

当使用websocket的时候,AUrl是 'ws://xxxx',协议应该是 http。 应用目录里面没有libcripto.dll。 #122

Open
wqmeng opened this issue Mar 3, 2024 · 9 comments

Comments

@wqmeng
Copy link

wqmeng commented Mar 3, 2024

这时,仍然会尝试使用 https 创建httpclient,导致抛出‘没有可用的libcripto库’ 异常。
procedure TCrossWebSocketMgr.CreateHttpClis;
begin
inherited; // 这里直接通过父类调用 CreateHttpCli(https); 这里的 https 并没有与 AUrl里面的具体的协议进行验证。

CreateHttpCli(WS);
CreateHttpCli(WSS);
end;

实际调用的时候,是否应该根据创建websocketclient的时候,提供的 AUrl ws来只创建 http 的?

@winddriver
Copy link
Owner

这是最近一次的更新改成这样的,目的是为了减少实际使用过程中的线程锁
倒是可以考虑再改进一下,增加一个是否使用ssl的参数,在确实不需要ssl的时候就不预先创建ssl对象了

@wqmeng
Copy link
Author

wqmeng commented Mar 4, 2024

ssl对象 最好是在客户open连接的时候,根据AUrl来设定,如果没有 wss 或者 https 的时候,就不需要创建。已经创建的,使用完成后,可能需要存放入一个队列里面,反复使用。

@winddriver
Copy link
Owner

本来就是这么设计的,不过即便这样,只要动态创建,在多线程环境就需要加锁以保护队列对象
改成预先创建,后续直接读取无需修改,就不用再加锁了

@wqmeng
Copy link
Author

wqmeng commented Mar 4, 2024

如果这样设计,那么使用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库,再抛出异常。

@winddriver
Copy link
Owner

更新了一下代码,增加了一个Prepare方法,由用户自行调用预创建
后续使用的部分还是需要加锁,先这样吧,这个锁的性能损失应该可以接受

@wqmeng
Copy link
Author

wqmeng commented Mar 4, 2024

如果想去掉锁,按我提供的方式也是可以的。创建的时候,ssl只要不影响 ws 和 http 创建就可以。 没有ssl环境可以抛出异常,但是ws 已经创建好,用户想只使用ws,不用ssl,只要忽略这个异常就行。 后面用户如果open的时候,使用了wss,正常抛出异常,这时候如果他还用wss,那他就应该自己准备ssl库。

毕竟忽略一个提醒异常的代价要比使用锁的代价要低的多。

@wqmeng
Copy link
Author

wqmeng commented Mar 4, 2024

刚刚测试了一下, 如果不用锁,需要内部处理异常,不然websocket对象不会被创建。 可以根据是否有ssl的情况,返回创建的状态,表明是否支持 ssl。

__WebSocket := TCrossWebSocket.Create('ws://' + Self.FSrvIPv4 + ':' + Self.FSrvPort);

这里 __WebSocket 可以加一个公开属性,以区别是否可以支持 ssl。 但是不再抛出异常,因为异常会导致 __WebSocket 为 nil。

@wqmeng
Copy link
Author

wqmeng commented Mar 4, 2024

把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;

@wqmeng
Copy link
Author

wqmeng commented Mar 7, 2024

如果使用调用Prepare方法的方式,是否以后调用的时候,都要提前Prepare一下。 Demo 都要修改?

还是觉得 http 和 https 两种模式分别创建,只是在创建https之前,先检测ssl库是否存在,如果不存在,直接跳过创建 https 对象不再提醒也不抛异常打断程序。

如果用户使用https模式,只在Open的时候才抛出异常。

这样处理的好处,

  1. 不使用https的时候,用户没有任何的影响,他也不知道是否创建过https的对象。
  2. 可以去掉对 https的 ssl对象的锁。
  3. 使用https的用户,也不会影响,在Open的时候,他一样需要准备ssl库。
  4. 因为提前创建的时候不抛出异常,在开发的时候,使用 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。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants