目录
一、WebSocket 控件程序结构
WebSocket控件为单文件,源文件名称为:uWebSocket_Component.pas,同时包含一个图标文件TWebSocket.dcr
二、WebSocket控件实现功能
- 接收客户端文本消息
- 发送客户端文本消息
- 接收客户端二进制流消息
- 发送客户端二进制流消息
- ping功能
- 全部断开客户端功能
- 广播消息功能
- 获取当前在线客户端列表功能
- 获取当前在线客户端数量功能
- 记录各个客户端发送和接收消息数量功能
三、WebSocket控件基本数据结构定义
const
CWebSocket_KEY = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; //标准要求的
type
TClientInfo = record
ClientIP : string;
ClientPort : Word;
ConnectTime : TDateTime; //连接成功时间
HandshakeTime : TDateTime; //握手成功时间
ping_Timeout : TDateTime; //发送ping命令之后,需要在这个时间之前得到回复,如果没有得到回复,则需要挂断客户端 0:表示没有发送ping命令
R_Last_Text : string; //最后一次接收到的文本数据
S_Last_Text : string; //最后一次发送的数据
R_Count : integer; //接收的消息次数
S_Count : integer; //发送的消息次数
ID : string; //唯一的索引 是 ClientIP + ':' + ClientPort
DisConnect : Boolean; //断开客户端连接
User_Agent : string;
end;
//创建一个包含客户端连接信息的ContextClass
TMyContext = class(TIdServerContext)
ClientInfo: TClientInfo;
end;
TOnStartup = procedure(Sender : TObject) of object; //服务器启动事件
TOnShutdown = procedure(Sender : TObject) of object; //服务器关闭事件
TOnConnect = procedure(ClientID : string) of object;
TOnDisConnect = procedure(ClientID : string) of object;
TOnError = procedure(ClientID : string; ErrorMsg : string) of object;
TOnException = procedure(Sender : TObject; ErrorMsg : string) of object;
TOnHandhake = procedure(ClientID : string; WebSocket_Key,WebSocket_Version,User_Agent : string) of object;
TOnMessage = procedure(ClientID : string; Text_Message : string) of object;
TOnBinary = procedure(ClientID : string; Bytes_Message : TBytes) of object;
TOnPong = procedure(ClientID : string; Text_Message : string) of object;
四、Websocket控件属性
Active属性为只读属性,表示WebSocket服务是否已经打开,True表示打开,False表示关闭。
编号 | 属性 | 说明 |
1 | HandShakeTimeOut | 握手超时时间,单位:秒。该参数表示从开始接收握手信号到完整接收到全部握手信息的时间,如果超过这个时间,表示握手失败,默认值是10秒。 |
2 | HeartBeat | 逻辑型,为True表示需要定时发送心跳命令,也就是ping命令,为False则不发送,默认:False; |
3 | interval | 发送心跳命令(ping)的时间间隔,这个属性和HeartBeat参数配合使用,单位是秒,默认值:20秒; |
4 | MaxConnectons | 表示WebSocket服务最多可以同时连接多少个客户端,0表示不限制,默认是0; |
5 | PingTimeout | 表示服务器发送ping命令后,多长时间必须收到客户端的返回pong,超过这个时间,表示ping失败,说明客户端已经断开,单位是秒,默认值10秒; |
6 | ReadTimeout | 该参数主要是为了解决indy的TCP服务占用CPU时间的问题,该值为0表示全速跑动线程,这样就会表现在CPU占用过多,所以一般会设置这个值,来降低CPU使用率,单位是毫秒,默认值是10毫秒。 |
7 | WebPort | 表示的是WebSocket的监听端口,默认设置:80 |
五、WebSocket公用方法
编号 | 方法 | 说明 |
1 | procedure Start_WebSocketServer; | 打开WebSocket服务,Acitve属性会变为True。 |
2 | procedure Stop_WebSocketServer; | 关闭WebSocket服务,Active会变为False。 |
3 | procedure DisconnectAll | 表示断开当前所有的客户端连接。 |
4 | procedure ping(ClientID : string; Application_data : string = '') | ping客户端,检查客户端是否处于活动状态。ClientID表示需要检查的客户端ID,Application_data表示应用数据,客户端会照样返回给服务器端。 |
5 | function Connections : TStringList; | 返回WebSoket当前有效的客户端连接列表,返回的是ClientID列表 |
6 | function Count : Word; | 返回当前有效连接的客户端数量 |
7 | function WriteBytes(const ClientID : string; Bytes_Message : TBytes; var ErrorMsg : string): Boolean; | 给客户端发送字节流消息,ClientID表示客户端ID,Bytes_Message表示发送的字节流。ErrorMsg表示错误信息,只有在结果为False的情况下才有效。 |
8 | function WriteTexts(const ClientID : string; Text_Message : string; var ErrorMsg : string): Boolean; | 给客户端发送文本消息,ClientID表示客户端ID,Text_Message表示发送的文本字符串。ErrorMsg表示错误信息,只有在结果为False的情况下才有效。 |
9 | procedure Broadcast(Text_Message : string); //广播消息给所有客户端,不判断是否成功 | 给所有的已连接在线客户端广播消息 |
10 | function Get_ClientInfo(ClientID : string) : TClientInfo; | 返回客户端的详细信息,ClientID表示客户端ID,结果返回TClientInfo表示客户端详细信息记录。 |
六、WebSocket事件
序号 | 事件 | 说明 |
1 | OnStartup | WebSocket服务器启动成功触发这个事件 |
2 | OnShutdown | WebSocket服务器停止后触发这个事件 |
3 | OnConnect | 客户端连接上WebSocket服务器后触发这个事件,参数有ClientID |
4 | OnDisConnect | 客户端断开连接后会触发这个事件,参数有ClientID |
5 | OnError | 发生错误时触发这个事件,事件参数有ClientID和ErrorMsg表示错误信息 |
6 | OnException | 当执行过程中出现异常时触发这个事件,只有ErrorMsg表示错误信息参数 |
7 | OnHandhake | 客户端握手成功后触发这个事件,参数有三个:WebSocket_Key,WebSocket_Version,User_Agent |
8 | OnMessage | 当收到客户端发送来的文本信息时触发这个事件,参数包括ClientID和Text_Message表示发送的文本字符串 |
9 | OnBinary | 客户端发送来字节流信息后触发这个事件,参数包括ClientID和Bytes_Message表示发送的字节流信息 |
10 | OnPong | 服务器端收到客户端发送的Pong信息时触发这个事件,参数包括ClientID和Text_Message表示发送pong字符串 |
特别说明:
以下事件属于在WebSocket线程中回调,所以书写事件处理函数时需要注意VCL是不安全的,在我的测试Demo里边并没有进行专门处理,是因为为了演示简单,演示程序也没有出现问题,实际是不安全并不表示一定出问题。
- OnHandhake
- OnMessage
- OnBinary
- OnPong
七、WebSocket控件需要完善部分
websocket控件基本功能已经实现,但是目前还有以下部分需要后续完善:
- 没有实现wss,目前只实现了ws,这就类似HTTP协议还不支持ssl,后续有机会完善,如果有人愿意完善,非常感激;
- 没有实现子协议,只是实现了标准。
对于不支持wss,在一般的Web应用开发中是没有问题的,但是在微信小程序中是不行的(因为需要ssl支持),微信公众号是可以的。