>UPDATE3:我与开发人员取得了联系。他说这是一个错误,现在他正试图修复它。所以我认为这个问题得到了回答。(该错误存在于版本 3.4 中(
UPDATE3完
结UPDATE2:它只会用很长的字符串冻结。现在两个版本都在代码中。
UPDATE2结束
更新:我查找了可用的替代方案(这里:Delphi的WebSocket服务器实现(,并开始测试ics-websockets(https://github.com/fajar-khairil/ics-websockets(。我在通过 wlan 连接到服务器的移动设备上启动了 websocket。如果我超出范围,服务器将继续发送数据而不会冻结,然后在某个时候关闭连接。在我看来,这就是它应该的方式。我想我会尝试联系来自埃塞盖斯的人。也许他们知道我做错了什么。更新结束
我在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 中并激活计时器。计时器每 500 毫秒触发一次 TForm1.Timer1Timer 过程。
WebSocketServer 上的"ThreadPool"选项是否处于活动状态并不重要......问题仍然存在。
在我的示例中,我使用了 TsgcWebSocketServer 和计时器的可视组件。如果有帮助,我可以重写测试,以便直接在源代码中创建它们。
这是 3.4 版中的一个错误,因此您只需要等待修复。