TsgcWebSocketServer
TsgcWebSocketServer实现了服务器WebSocket组件,可以处理多线程客户端连接。按照以下步骤配置此组件:
标准:
将TsgcWebSocketServer组件拖到表单上
设置端口(默认值为80)。如果您位于防火墙后面,则可能需要对其进行配置。
设置允许的规格,默认情况下允许所有规格。
-RFC6455:是标准和推荐的WebSocket规范。
-Hixie76:这是一个草稿,如果你想支持Safari 4.2这样的旧浏览器,只建议建立Hixie76连接
4.如果需要,可以处理事件:
-OnConnect:每次建立WebSocket连接时,都会触发此事件。
-OnDisconnect:每次断开WebSocket连接时,都会触发此事件。
-OnError:每次出现WebSocket错误(如错误的握手)时,都会触发此事件。
-OnMessage:每当客户端发送文本消息并被服务器接收时,就会触发此事件。
-OnBinary:每当客户端发送二进制消息并被服务器接收时,就会触发此事件。
-OnHandhake:在服务器端评估握手之后激发此事件。
-OnException:每次发生异常时,都会触发此事件。
-OnAuthentication:如果启用了身份验证,则触发此事件。您可以检查客户端传递的用户和密码,并启用/禁用Authenticated Variable。
-OnUnknownProtocol:如果未检测到WebSocket协议(例如,因为客户端使用的是普通TCP协议),在这种情况下,可以接受或拒绝连接。
-OnStartup:服务器启动后引发。
-OnShutdown:服务器停止后引发。
-OnTCPConnect:公共事件,称为TCP连接后和Websocket握手前。当您的服务器接受普通TCP连接时(因为OnConnect事件仅在客户端发送第一条消息后触发),这一点非常有用。
-OnBeforeHeartBeat:如果启用了HeartBeat,则允许将自定义HeartBeat设置Handled参数设置为True(这意味着不会发送标准的websocket ping)。
5. 创建一个过程并设置属性Active=True。
最常见的用途
1.Server Start(服务启动)
要启动服务器,首先必须设置侦听端口,默认情况下,该端口设置为端口80,但您可以更改任何端口。设置端口后,有两种方法可以启动服务器。
Active Property(活动属性)
若将Active属性设置为true,服务器将开始侦听端口集上的所有传入连接。
oServer := TsgcWebSocketServer.Create(nil); oServer.Port := 80; oServer.Active := true;
若将Active属性设置为false,服务器将停止并关闭所有活动连接。
oServer.Active := false;
Start / Stop methods(启动/停止方法)
如果调用Active属性,启动/停止服务器的过程在同一线程中完成,则调用start和stop方法将在辅助线程中执行。
oServer := TsgcWebSocketServer.Create(nil); oServer.Port := 80; oServer.Start();
若调用Stop()方法,服务器将停止并关闭所有活动连接。
oServer.Stop();
您可以使用ReStart方法在辅助线程中停止和启动服务器。
如果在关闭服务器后更改端口,要开始侦听其他端口,请调用Bindings方法。在关闭服务器后清除()以删除所有以前的绑定。否则,服务器将尝试绑定到以前的绑定。
2:Server Bindings(服务器绑定)
默认情况下,如果您只填写Port属性,服务器将绑定所有IP的侦听端口,因此,如果您有3个IP:127.0.0.1、80.5411.22和12.55.41.17。您的服务器将在3个IP上绑定此端口。
通常建议只绑定到所需的IP,这里是您可以使用Bindings属性的地方。
不要使用Port属性,只需使用Binding属性并填写所需的IP和Port。
oServer := TsgcWebSocketServer.Create(nil); With oServer.Bindings.Add do begin IP := '127.0.0.1'; Port := 5555; end; With oServer.Bindings.Add do begin IP := '80.58.25.40'; Port := 5555; end; oServer.Active := true;
如果在关闭服务器后更改端口,要开始侦听其他端口,请调用Bindings方法。在关闭服务器后清除()以删除所有以前的绑定。否则,服务器将尝试绑定到以前的绑定。
3:Server Startup - Shutdown(服务器启动-关闭)
一旦您设置了服务器的所有必需配置,就有两个有用的事件可以知道服务器何时启动和何时停止。
OnStartup(启动时)
当服务器启动并可以处理新连接时,将触发此事件。
procedure OnStartup(Sender: TObject); begin WriteLn('#server started'); end;
OnShutdown(关闭时)
此事件在服务器停止且不再接受连接后激发。
procedure OnShutdown(Sender: TObject); begin WriteLn('#server stopped'); end;
4:Server Keep Active(服务器保持活动)
一旦服务器启动并触发OnShutdown事件,有时服务器会因任何原因停止。如果要在意外关闭后重新启动服务器,可以使用WatchDog属性
WatchDog(看门狗)
如果启用了看门狗,当服务器检测到关机时,看门狗会尝试每X秒重新启动一次,直到服务器再次处于活动状态。
示例:意外停止后,每10秒重新启动一次,尝试次数不限。
oServer := TsgcWebSocketServer.Create(nil); oServer.WatchDog.Interval := 10; oServer.WatchDog.Attempts := 0; oServer.WatchDog.Enabled := true; oServer.Active := true;
连接
1:Server Keep Connections Alive(服务器保持连接活动)
一旦您的客户端连接到服务器,有时会由于信号差、连接错误而关闭连接……使用心跳来保持连接。
HeartBeat(心跳包)
HeartBeat属性允许每X秒发送一次Ping以保持连接活动。如果对等端之间没有数据交换,某些服务器会关闭TCP连接。HeartBeat解决了这个问题,每特定间隔发送一次ping。通常,这足以保持连接处于活动状态,但若在X秒后未收到来自客户端的响应,则若要关闭连接,可以设置超时间隔。
示例:每30秒向所有连接的客户端发送ping
oServer := TsgcWebSocketServer.Create(nil); oServer.HeartBeat.Interval := 30; oServer.HeartBeat.Timeout := 0; oServer.HeartBeat.Enabled := true; oServer.Active := true;
2:Server Plain TCP(服务器普通TCP)
WebSocket服务器接受WebSocket、HTTP、SSE…协议,但也可以使用普通的tcp连接。
有2个事件,可用于更好地处理TCP连接。
OnTCPConnect
在客户端连接到服务器之后以及客户端和服务器之间的任何握手之前调用此事件。OnConnect事件仅在客户端发送消息后激发(以允许服务器检测要使用的协议)。
此事件允许您知道新客户端正在尝试连接到服务器,并且服务器可以接受或不接受该连接。
OnUnknownProtocol
当服务器从客户端接收到第一条消息但无法检测是否存在任何已知协议时,将调用此事件。在这种情况下,服务器可以接受或不接受协议
OnEvent
如果连接是纯TCP,则在OnUnknownProtocol事件中接受协议后,在成功且完整的连接后激发此事件。
身份验证
1>Server Authentication(服务器身份验证)
TsgcWebSocket服务器支持3种类型的身份验证:
1.Basic:在WebSocket HandShake期间读取HTTP头,用户和密码编码为基本授权。
2.Session:第一个客户端向服务器请求HTTP会话,若服务器返回会话,则在WebSocket HandShake的GET HTTP Header中传递。(*sgcWebSockets库自己的授权方法)。
3.URL:使用WebSocket HandShake的GET HTTP头读取请求授权。(*sgcWebSockets库自己的授权方法)。
您可以使用AuthUsers属性设置Authenticated用户列表,只需使用以下格式设置用户:user=password
OnAuthentication
每次服务器从客户端接收到身份验证请求时,都会调用此事件以返回用户是否经过身份验证。
使用Authenticated参数接受或不接受连接。
procedure OnAuthentication(Connection: TsgcWSConnection; aUser, aPassword: string; var Authenticated: Boolean); begin if ((aUser = 'user') and (aPassword = 'secret')) then Authenticated := true else Authenticated := false; end;
OnUnknownAuthentication
如果默认情况下不支持身份验证(如JWT),您仍然可以使用此事件接受或不接受连接。只需读取参数并接受或不接受连接。
procedure OnUnknownAuthentication(Connection: TsgcWSConnection; AuthType, AuthData: string; var aUser, aPassword: string; var Authenticated: Boolean); begin if AuthType = 'Bearer' then begin if AuthData = 'jwt_token' then Authenticated := true else Authenticated := false; end else Authenticated := false; end;
发送消息
1>Server Send Text Message(服务器发送文本消息)
一旦客户端连接到服务器,它就可以向服务器发送文本消息。要发送文本消息,只需调用WriteData()方法并发送文本消息。
Send a Text Message(发送一条文本消息)
调用To WriteData()方法并发送文本消息。此方法在调用的同一线程上执行。
TsgcWebSocketClient1.WriteData('My First sgcWebSockets Message!.');
如果QueueOptions.Text具有与qmNone不同的值,而不是在调用的同一线程上处理,而是在辅助线程上处理。默认情况下,此选项被禁用。
2>Server Send Binary Message(服务器发送二进制消息)
一旦客户端连接到服务器,服务器就可以发送二进制消息。要发送二进制消息,只需调用WriteData()方法向单个客户端发送消息,或使用Broadcast向所有客户端发送消息
Send a Text Message
调用To WriteData()方法并发送二进制消息。
TsgcWebSocketServer1.WriteData('guid', TMemoryStream.Create);
如果QueueOptions.Binary的值与qmNone的值不同,它不会在调用的同一线程上处理,而是在辅助线程上处理。默认情况下,此选项被禁用。
如果属性IOHandlerOptions,则QueueOptions不起作用。IOHandlerType=iohIOCP(由于IOCP架构,不支持此功能)。
您也可以从TsgcWSConnection调用WriteData()方法,例如:在连接到服务器时向客户端发送消息。
procedure OnConnect(Connection: TsgcWSConnection); begin Connection.WriteData(TMemoryStream.Create); end;
Send a message to ALL connected clients(向所有连接的客户端发送消息)
调用To Broadcast()方法向所有连接的客户端发送二进制消息。
TsgcWebSocketServer1.Broadcast(TMemoryStream.Create);
收消息
1>Server Receive Text Message(服务器接收文本消息)
当服务器接收到文本消息时,OnMessage事件被触发,只需读取Text参数即可知道接收到的消息字符串。
procedure OnMessage(Connection: TsgcWSConnection; const Text: string); begin ShowMessage('Message Received from Client: ' + Text); end;
默认情况下,服务器使用neAsynchronous方法来调度OnMessage事件,这意味着该事件是在主线程的上下文中执行的,因此更新表单的任何控件都是线程安全的。
如果您的服务器接收到大量消息,或者您需要控制与其他线程的同步,请将NotifyEvents属性设置为neNoSync,这意味着OnMessage事件将在连接线程的上下文中执行,因此如果您需要更新表单的任何控制或访问共享对象,则必须实现自己的同步方法。
2>Server Receive Binary Message(服务器接收二进制消息)
当服务器接收到二进制消息时,OnBinary事件被触发,只需读取Data参数即可知道接收到的二进制消息。
procedure OnBinary(Connection: TsgcWSConnection; const Data: TMemoryStream); var oBitmap: TBitmap; begin oBitmap := TBitmap.Create; Try oBitmap.LoadFromStream(Data); Image1.Picture.Assign(oBitmap); Log( '#image uncompressed size: ' + IntToStr(Data.Size) + '. Total received: ' + IntToStr(Connection.RecBytes)); Finally FreeAndNil(oBitmap); End; end;
默认情况下,服务器使用neAsynchronous方法来调度OnMessage事件,这意味着该事件是在主线程的上下文中执行的,因此更新表单的任何控件都是线程安全的。
如果您的服务器接收到大量消息,或者您需要控制与其他线程的同步,请将NotifyEvents属性设置为neNoSync,这意味着OnMessage事件将在连接线程的上下文中执行,因此如果您需要更新表单的任何控制或访问共享对象,则必须实现自己的同步方法。
方法:
Broadcast:向所有连接的客户端发送消息。
-Message / Stream:要发送到所有客户端的消息或流。
-Channel:如果指定频道,则消息将仅发送给订户.
-Protocol:如果已定义,则消息将仅发送到特定协议。
-Exclude:如果已定义,则排除连接guid的列表(用逗号分隔)。
-Include:如果已定义,则包含连接guid列表(用逗号分隔)。
WriteData:向单个或多个客户端发送消息。每当客户端建立WebSocket连接时,此连接都由Guid标识,您可以使用此Guid向客户端发送消息。
Ping:向所有连接的客户端发送ping。如果指定了超时,它将等待响应,直到超过超时,如果没有响应,则关闭连接。
DisconnectAll:断开所有活动连接。
Start:使用辅助线程连接到服务器,这可以防止应用程序在尝试连接时冻结。
Stop:使用辅助线程断开与服务器的连接,这可以防止应用程序在尝试断开连接时冻结。
属性:
Authentication:如果启用,则可以根据用户名和密码验证WebSocket连接。
-Authusers:身份验证用户
-Session:客户端需要执行HTTP GET传递用户名和密码,如果经过身份验证,服务器将响应会话ID。使用此会话ID,客户端将打开WebSocket连接作为参数传递。
-URL:客户端打开Websocket连接,将用户名和密码作为参数传递。
-Basic:实现基本访问身份验证,仅适用于VCL web套接字(服务器和客户端)和HTTP请求(客户端web浏览器不实现这种类型的身份验证)。
Bindings:用于管理IP和端口。
Connections:包含所有客户端连接的列表。
Count:连接数计数。
LogFile:如果启用,则将套接字消息保存到指定的日志文件,这对于调试非常有用。
-Enabled:如果每次通过套接字接收和发送消息时都启用,则消息将保存在文件中。
-FileName:文件名的完整路径。
-UnMaskFrames:默认情况下,True表示保存未屏蔽接收的websocket消息。
Extensions:您可以对发送的消息启用压缩(如果客户端不支持压缩,消息将自动交换而不进行压缩)。
FallBack:如果浏览器本机不支持WebSockets协议,则可以启用以下回退:
-Flash:如果启用,如果浏览器没有本机WebSocket实现并且启用了flash,则使用flash作为传输。
-ServerSentEvents:如果启用,则允许从服务器向浏览器客户端发送推送通知。
-Retry:尝试重新连接到服务器的时间间隔(秒)(默认值为3)。
-HeartBeat:如果启用,则尝试保持Websocket客户端连接每x秒发送一次ping。
-Interval:每次ping之间的秒数。
-Timeout:超时连接
TCPKeepAlive:如果启用,则在TCP套接字级别使用keep-alive,在Windows中将启用SIO_KEEPALIVE_VALS(如果支持),如果不支持,则使用keep-alive。默认情况下禁用。
-Interval:以毫秒为单位。
-Timeout:以毫秒为单位。
HTTP2Options:默认情况下,HTTP/2协议未启用,它使用HTTP1.1处理HTTP请求。如果客户端支持HTTP/2协议,则启用此属性。
-Enabled:如果为true,则支持HTTP/2协议。如果客户端不支持HTTP/2,则HTTP 1.1将用作回退(fallback)。
-Settings:指定要发送到HTTP/2服务器的标头值。
--EnablePush:默认情况下,此设置可用于避免服务器向客户端推送内容。
--HeaderTableSize:允许发送方通知远程端点用于解码标头块的标头压缩表的最大大小(以八位字节为单位)。编码器可以通过使用特定于报头块内的报头压缩格式的信令来选择等于或小于该值的任何大小。初始值为4096个八位字节。
--InitialWindowSize:指示流级流控制的发送方初始窗口大小(以八位字节为单位)。初始值为65535个八位字节。此设置会影响所有流的窗口大小。
--MaxConcurrentStreams:指示发送方将允许的最大并发流数。这个限制是定向的:它适用于发送方允许接收方创建的流的数量。最初,该值没有限制。
--MaxFrameSize:指示发送方愿意接收的最大帧有效负载的大小(以八位字节为单位)。初始值为16384个八位字节。
--MaxHeaderListSize:此建议设置以八位字节为单位通知对等方发送方准备接受的最大标头列表大小。该值基于标头字段的未压缩大小,包括名称和值的长度(以八位字节为单位)加上每个标头字段32个八位字节的开销。
IOHandlerOptions:默认情况下使用普通的IndyHandler(每个连接都在自己的线程中运行)
-iohDefault:默认indy IOHandler,每个新连接都会创建一个新线程。
-iohIOCP:仅适用于windows,需要sgcWebSockets Enterprise Edition,线程池处理所有连接。
-iohEPOLL:仅适用于linux,需要sgcWebSockets Enterprise Edition,线程池处理所有连接。
LoadBalancer:它是一个连接到负载平衡器服务器的客户端,用于广播消息和发送有关服务器的信息。
AutoRegisterBindings:如果启用,将自动向负载平衡器服务器发送服务器绑定。
AutoRestart:负载平衡器服务器连接断开并尝试重新连接后的等待时间(秒);零表示无重启(默认);
Bindings:在这里,您可以设置要发送到负载平衡器服务器的手动绑定,例如:
WS://127.0.0.1:80 WSS://127.0.0.2:8888
-Enabled:如果启用,它将连接到负载平衡器服务器。
-Guid:用于标识负载平衡器服务器端的服务器。
-Host:连接主机IP或者域名
-Port:连接端口
MaxConnections:允许的最大连接数(如果为零,则没有限制)。
NotifyEvents:定义通知WebSocket事件的模式。
-neAsynchronous:这是默认模式,在异步模式下通知线程事件,将事件添加到与主线程异步同步的队列中。
-neSynchronous:如果选择此模式,则在同步模式下通知线程事件,需要与主线程同步以通知这些事件。
-neNoSync:与主线程没有同步,如果需要访问非线程安全的控件,则需要实现自己的同步方法。
Options:选项
-FragmentedMessages:允许处理碎片消息
--frgOnlyBuffer:消息被缓冲,直到接收到所有数据,它引发OnBinary或OnMessage事件(默认选项)
--frgOnlyFragmented:每次接收到新片段时,它都会引发OnFragmented事件。
--frgAll:每次接收到新片段时,它都会引发OnFragmented Event,其中包含从第一个数据包接收到的所有数据。当接收到所有数据时,它会引发OnBinary或OnMessage事件。
-HTMLFiles:如果启用,则允许请求默认启用的Web浏览器测试。
-JavascriptFiles: 如果启用,则允许请求默认启用的Javascript内置库。
-RaiseDisconnectExceptions:默认情况下启用,每次发生协议错误导致的断开连接时都会引发异常。
-ReadTimeOut:检查套接字连接中是否有数据的时间(毫秒),默认值为10。
-WriteTimeOut:将数据发送到其他对等端的最长时间(以毫秒为单位),默认为0(仅适用于Windows操作系统)。
-ValidateUTF8:如果启用,则验证消息是否包含UTF8有效字符,默认情况下禁用。
QueueOptions:
此属性允许在内部队列中对消息进行排队(而不是直接发送),并在连接线程的上下文中发送消息(QueueOptions仅适用于基于Indy的服务器,其中每个连接都在其自己的线程中运行),这防止了多个线程尝试使用同一连接发送消息时出现锁定。对于每种消息类型:文本、二进制或Ping,都可以配置队列,默认情况下,值集为qmNone,这意味着消息不排队。其他类型表示不同的队列级别,它们之间的区别只是处理顺序(首先是qmLevel1,然后是qmLevel2,最后是qmLevel3)。
示例:如果文本和二进制消息的属性设置为qmLevel2,Ping设置为qmLevel1。服务器将首先处理Ping消息(因此,如果文本或二进制消息在同一时间排队,则会先发送Ping消息),然后在同一队列中处理文本和二进制邮件。IOHandlerOptions=iohIOCP时不支持QueueOptions。
ReadEmptySource:读取HTTP连接且未接收到数据的最大次数,默认为0(表示无限制)。如果达到限制,连接将关闭。
SecurityOptions:
-OriginsAllowed:在这里定义允许哪些源(默认情况下接受来自所有源的连接),如果源不在列表中,则关闭连接。示例:
Allow all connections to IP 127.0.0.1 and port 5555. OriginsAllowed = "http://127.0.0.1:5555"
Allow all connections to IP 127.0.0.1 and all ports. OriginsAllowed = "http://127.0.0.1:*"
Allow all connections from any IP. OriginsAllowed = ""
SSL:启用安全连接。
SSLOptions:用于定义SSL属性:证书文件名、密码。。。
-RootCertFile:根证书文件的路径。
-CertFile:PEM格式的证书文件的路径。
-KeyFile:PEM格式的证书密钥文件的路径。
-Password:如果证书使用密码保护,请在此处设置。
-VerifyCertificate:如果必须验证证书,请启用此属性。
-VerifyCertificate_Options:
--FailfIfNoCertificate:如果客户端没有返回证书,TLS/SSL握手将立即终止,并发出“握手失败”警报。
--VerifyClientOnce:仅在初始TLS/SSL握手时请求客户端证书。在重新协商的情况下,不要再次请求客户端证书。
-VerifyDepth:是Integer属性,表示对X.509证书执行验证时允许的最大链接数。
-Version:默认情况下,从较新到较低协商所有可能的TLS版本。可以选择特定的TLS版本。
--tlsUndefined:这是默认值,客户端将尝试协商所有可能的TLS版本(从最新到最旧),直到成功连接。
--tls1_0:实现TLS 1.0
--tls1_1:实现TLS 1.1
--tls1_2:实现TLS 1.2
--tls1_3:实现TLS 1.3
-OpenSSL_Options:
--APIVersion:允许定义将使用哪个OpenSSL API。
---oslAPI_1_0:使用API 1.0 OpenSSL,它是Indy最新支持的
---oslAPI_1_1:使用API 1.1 OpenSSL,需要我们的自定义Indy库,并允许使用OpenSSL 1.1.1库(支持TLS 1.3)。
---oslAPI_3_0:使用API 3.0 OpenSSL,需要我们的自定义Indy库,并允许使用OpenSSL 3.0.0库(支持TLS 1.3)。
--LibPath:在这里,您可以配置openSSL库的位置
---oslpNone:这是默认设置,openSSL库应位于二进制文件所在的同一文件夹中或位于已知路径中。
---oslpDefaultFolder:为所有IDE角色自动设置库应位于的openSSL路径。
---oslpCustomFolder:如果选择了此选项,请在LibPathCustom属性中定义完整路径。
--LibPathCustom:当LibPath=oslpCustomFolder时,在此处定义openSSL库所在的完整路径。
--UnixSymLinks:启用或禁用Unix系统下SymLinks的加载(默认情况下已启用,OSX64下除外):
---oslsSymLinksDefault:默认情况下,除了在OSX64下(在MacOSMonterey尝试加载没有版本的库失败之后)。
---oslsSymLinksLoadFirst:加载SymLinks并在尝试加载版本库之前执行。
---oslsSymLinksLoad:尝试加载版本库后加载SymLinks。
---oslsSymLinksDontLoad:不要加载SymLinks。
--ECDHE:如果启用,则使用ECDHE而不是RSA作为密钥交换。如果使用OpenSSL 1.0.2,建议启用ECDHE。
ThreadPool:如果启用,当不再需要线程时,将其放入池中并标记为非活动(不消耗CPU周期),如果存在大量短时间连接,则非常有用。ThreadPool与IOCP不兼容,因此请在启用IOCP时不要启用它。
-MaxThreads:要创建的最大线程数,默认为0,表示没有限制。如果达到最大数量,则拒绝连接。
-PoolSize:ThreadPool的大小,默认为32。
WatchDog:如果启用,则在意外断开连接后重新启动服务器。
-Interval:X秒后重新连接。
-Attempts:最大重新连接次数,如果为零,则无限制。
Throttle:用于限制每秒发送/接收的比特数。
目录 返回
首页