UPDATE3: I got in touch with the developer. He says it is a bug and right now he is trying to fix it. So i think this question is answered. (The bug is present in version 3.4)
UPDATE3 END
UPDATE2: It will only freeze with a very long string. Now both versions are in the code.
UPDATE2 END
UPDATE: I looked up what alternatives are available (here: WebSocket server implementations for Delphi) and started to test the ics-websockets (https://github.com/fajar-khairil/ics-websockets). I started the websocket on a mobile device connected via wlan to the server. If i get out of range the server continues to send data without freezing and then at some point it closes the connection. In my opinion that is the way it is supposed to be.. I think i will try to contact the guys from esegece. Maybe they know what i am doing wrong.. UPDATE END
I am using an sgcWebSocketServer (newest Version 3.4 Homepage: http://websockets.esegece.com/) in Delphi XE5. The client side uses a javascript websocket embedded in a html file.
If i connect with a wireless client and send repeatedly message from the server to the client, the server will freeze for 10-30 seconds if the client looses connection. It looks like a basic timeout problem, but only a wireless client would freeze the server.
Why is this happening? I dont think i should need to check the connection of every client before sending data through the websocket. (Also i wouldnt know how)
As far as i know there is only one method to write data (WriteData), so what should i do? How can i prevent this freeze? The sgcWebSocketServer component is multithreaded, at least the documentation says so.. So i dont think putting the WriteData in a thread will be a nice solution.
Here is my html code:
<!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>
This is my Main Unit in Delphi:
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.
Once the client connects i save the guid in sGUID and activate the timer. The timer fires every 500ms the TForm1.Timer1Timer procedure.
It doesnt matter if the "ThreadPool" option on the WebSocketServer is active or not.. the problem remains.
In my example i used the visual components of the TsgcWebSocketServer and the timer. If it helps i can rewrite the test so they will be created directly in the source code.