为什么如果无线客户端失去连接,sgcWebSocketServer会冻结?

时间:2015-10-13 17:37:31

标签: multithreading delphi websocket

UPDATE3: 我与开发人员联系过。他说这是一个错误,现在他正试图修复它。所以我认为这个问题得到了回答。 (该错误出现在3.4版本中)

UPDATE3 END

UPDATE2: 它只会用很长的字符串冻结。现在两个版本都在代码中。

UPDATE2 END

更新 我查找了可用的替代方法(此处:WebSocket server implementations for Delphi)并开始测试ics-websockets(https://github.com/fajar-khairil/ics-websockets)。 我在通过wlan连接到服务器的移动设备上启动了websocket。如果我超出范围,服务器将继续发送数据而不冻结,然后在某些时候关闭连接。在我看来,这是应该的方式.. 我想我会尝试联系esegece的人。也许他们知道我做错了什么.. 更新结束

我在Delphi XE5中使用sgcWebSocketServer(最新版本3.4主页:http://websockets.esegece.com/)。 客户端使用嵌入在html文件中的javascript websocket。

如果我连接无线客户端并重复从服务器向客户端发送消息,如果客户端断开连接,服务器将冻结10-30秒。它看起来像是一个基本的超时问题,但只有无线客户端会冻结服务器

为什么会这样?我不认为我应该在通过websocket发送数据之前检查每个客户端的连接。 (我也不知道如何)

据我所知,只有一种方法可以写入数据(WriteData),那我该怎么办?我该如何防止这种冻结? sgcWebSocketServer组件是多线程的,至少文档是这样说的。所以我不认为将WriteData放在一个线程中将是一个很好的解决方案。

这是我的HTML代码:

<!DOCTYPE html>

<meta charset="utf-8" />

<title>WebSocket Test</title>

<script language="javascript" type="text/javascript">

  var wsUri = "ws://192.168.xxx.yyy:12345";
  var output;

  function init()
  {
    output = document.getElementById("output");
    testWebSocket();
  }

  function testWebSocket()
  {
    websocket = new WebSocket(wsUri);
    websocket.onopen = function(evt) { onOpen(evt) };
    websocket.onclose = function(evt) { onClose(evt) };
    websocket.onmessage = function(evt) { onMessage(evt) };
    websocket.onerror = function(evt) { onError(evt) };
  }

  function onOpen(evt)
  {
    writeToScreen("CONNECTED");
    doSend("WebSocket rocks");
  }

  function onClose(evt)
  {
    writeToScreen("DISCONNECTED");
  }

  function onMessage(evt)
  {
    writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
  }

  function onError(evt)
  {
    writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
  }

  function doSend(message)
  {
    writeToScreen("SENT: " + message); 
    websocket.send(message);
  }

  function writeToScreen(message)
  {
    var pre = document.createElement("p");
    pre.style.wordWrap = "break-word";
    pre.innerHTML = message;
    output.appendChild(pre);
  }

  window.addEventListener("load", init, false);

</script>

<h2>WebSocket Test</h2>

<div id="output"></div>

这是我在德尔福的主要部门:

unit U_Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, sgcWebSocket_Classes,
  sgcWebSocket_Server, sgcWebSocket, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    WebSocketServer: TsgcWebSocketServer;
    Timer1: TTimer;
    Memo1: TMemo;
    procedure WebSocketServerConnect(Connection: TsgcWSConnection);
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  sGUID : String;

implementation

{$R *.dfm}

procedure TForm1.Timer1Timer(Sender: TObject);
var
  bErgebnis: boolean;
  sData : String;
begin
  // Works
  bErgebnis := WebSocketServer.WriteData(sGUID,'DATA');
  // Will freeze
  sData := 'DATA!';
  for i := 0 to 100 do
  begin
    sData := sData + 'DATA!';
  end;
  bErgebnis := WebSocketServer.WriteData(sGUID,sData);
  Memo1.Lines.Add(TimeToStr(now()) + (bErgebnis.ToString()));
end;

procedure TForm1.WebSocketServerConnect(Connection: TsgcWSConnection);

begin
  sGUID := Connection.Guid;
  Timer1.Enabled := True;
end;

end.

一旦客户端连接,我将guid保存在sGUID中并激活计时器。计时器每隔500ms触发一次TForm1.Timer1Timer程序。

如果&#34; ThreadPool&#34; WebSocketServer上的选项是否有效..问题仍然存在。

在我的例子中,我使用了TsgcWebSocketServer和计时器的可视组件。如果它可以帮助我重写测试,那么它们将直接在源代码中创建。

1 个答案:

答案 0 :(得分:0)

这是版本3.4中的错误,因此您只需要等待修复。