为Delphi移动开发准备的跨平台异步Socket

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

为Delphi移动开发准备的跨平台异步Socket

Delphi
移动开发准备的跨平台异步Socket 浏
览:650
加⼊我的收藏
楼主:⼀、引⾔
在D10.1 Berlin之前,Delphi移动开发⼀直缺少⼀个使⽤⽅便、跨平台的异步socket控件,除了Indy组件,连最基本的socket单元都缺少。

所以,移动开发时实现移动客户端和电脑服务器之间、⼿机之间的异步通信⽐较困难。

本⼈以前在实现⼿机端的消息传输时,还是通过HTTP轮询形式实现,响应速度慢、服务端压⼒⼤,不适合⼤并发即时通信开发。

D10.1 Berlin版本发布之后,这样的局⾯改观了,因为Berlin中提供了⼀个跨平台Socket单元,尽管不是异步的,但是,通过我们通过使⽤多线程等技术的再度封装,就可以实现异步通信——收到消息、连通、断开、出错等,都激发相应的事件。

本⼈近⽇就为QuickBurro中间件的移动开发组件增加了⼀个跨平台的异步Socket控
件: TMBSocket。

下⾯的代码是类声明,后图⽰意其属性、事件:
type
TConnectedEvent = procedure(Sender: TObject; Socket: TSocket) of object;
TDisconnectedEvent = procedure(Sender: TObject; Socket: TSocket) of Object;
TDataArrivedEvent = procedure(Sender: TObject; Socket: TSocket) of Object;
TErrorEvent = procedure(Sender: TObject; Socket: TSocket; const Error: string; var CanClose: boolean) of Object; //
TMBSocket=class(TComponent)
private
RawSocket: TSocket;
fHostName: string;
fHostAddress: string;
fPort: integer;
fActive: boolean;
fConnected: boolean;
//
fOnConnect: TConnectedEvent;
fOnDisconnect: TDisconnectedEvent;
fOnDataArrive: TDataArrivedEvent;
fOnError: TErrorEvent;
//
procedure SetHostName(aHostName: string);
procedure SetHostAddress(aHostAddress: string);
procedure SetPort(aPort: integer);
procedure SetActive(aActive: boolean);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy(); override;
procedure Open;
procedure Close;
function SendBuff(const BufferPtr: pointer; const DataLength: integer): boolean;
procedure ReceiveData(const BufferPtr: pointer; const Bytes: integer);
function DataLength(): integer;
published
property HostName: string read fHostName write SetHostName;
property HostAddress: string read fHostAddress write SetHostAddress;
property Port: integer read fPort write SetPort;
property Active: boolean read fActive write SetActive;
property Connected: boolean read fConnected;
//
property OnConnect: TConnectedEvent read fOnConnect write fOnConnect;
property OnDisconnect: TDisconnectedEvent read fOnDisconnect write fOnDisconnect; property OnDataArrive: TDataArrivedEvent read fOnDataArrive write fOnDataArrive;
property OnError: TErrorEvent read fOnError write fOnError;
End;
此帖⼦包含附件:
PNG 图像
⼤⼩:21.1K
----------------------------------------------
樵夫的⼤马甲
作者: jopher3 (樵夫的马六甲)▲▲△△△
-
注册会员
2017-1-22
12:46:11
⼆、电脑端服务程序
为了测试⼿机端TMBSocket控件的异步通信效果,我们先⽤TServerSocket快速搭建⼀个测试服务器,让它与⼿机端程序进⾏通信。

下⾯是代码和运⾏效果:
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, BurroSocket;
type
TForm1 = class(TForm)
Memo1: TMemo;
Label1: TLabel;
Edit1: TEdit;
Server: TBServerSocket;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Memo2: TMemo;
procedure Button4Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure ServerListen(Sender: TObject; Socket: TBCustomWinSocket);
procedure ServerClientRead(Sender: TObject; Socket: TBCustomWinSocket);
procedure ServerClientConnect(Sender: TObject; Socket: TBCustomWinSocket); procedure ServerClientDisconnect(Sender: TObject;
Socket: TBCustomWinSocket);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//
// 开启服务...
procedure TForm1.Button1Click(Sender: TObject);
1楼:begin
server.Port:=strtoint(edit1.Text);
server.Active:=true;
end;
//
// 停⽌服务...
procedure TForm1.Button3Click(Sender: TObject);
begin
server.Active:=false;
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>服务器顺利停⽌服务。

'); end;
//
// 客户端连上来时...
procedure TForm1.ServerClientConnect(Sender: TObject;
Socket: TBCustomWinSocket);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <--有客户端连上来
了!IP='+string(Socket.RemoteAddress));
end;
//
// 客户端断开时...
procedure TForm1.ServerClientDisconnect(Sender: TObject;
Socket: TBCustomWinSocket);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <--有客户端断开
了!IP='+string(Socket.RemoteAddress));
end;
//
// 客户端数据送达时...
procedure TForm1.ServerClientRead(Sender: TObject; Socket: TBCustomWinSocket); var
j: integer;
tmpstr: ansistring;
begin
j:=socket.ReceiveLength;
setlength(tmpstr,j);
Socket.ReceiveBuf(tmpstr[1],j);
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <--收到'+inttostr(j)+'个字节:'); memo1.Lines.Add(string(tmpstr));
end;
//
// 向第⼀个客户端连接发送测试数据...
procedure TForm1.Button2Click(Sender: TObject);
var
tmpstr: ansistring;
begin
tmpstr:=ansistring(memo2.Lines.Text);
server.Socket.Connections[0].SendBuf(tmpstr[1],length(tmpstr));
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>向客户端发送了如下消息:'); memo1.Lines.Add(string(tmpstr));
end;
//
// 服务端⼝开始⼯作时...
procedure TForm1.ServerListen(Sender: TObject; Socket: TBCustomWinSocket); begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>服务器已启动,请⼿机端开始测试!');
end;
//
// 退出程序...
procedure TForm1.Button4Click(Sender: TObject);
begin
close;
end;
end.
此帖⼦包含附件:
PNG 图像
⼤⼩:6.8K
----------------------------------------------
樵夫的⼤马甲
作者: jopher3 (樵夫的马六甲)▲▲△△△
-
注册会员
2017-1-22 12:46:42
三、移动端异步通信测试程序
万事具备,我们来编写个⼿机端的异步通信客户端程序,让它与上⾯的简易测试服务器进⾏通信。

下⾯是测试程序源码、运⾏效果图:
unit main;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, .socket,
FMX.Objects, FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo,
MBSocket;
type
TForm1 = class(TForm)
Memo1: TMemo;
Rectangle1: TRectangle;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Rectangle2: TRectangle;
Label1: TLabel;
Button2: TButton;
Image1: TImage;
Memo2: TMemo;
MBSocket: TMBSocket;
Button1: TButton;
Image2: TImage;
StyleBook1: TStyleBook;
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure MBSocketConnect(Sender: TObject; Socket: TSocket);
procedure MBSocketError(Sender: TObject; Socket: TSocket;
const Error: string; var CanClose: Boolean);
procedure MBSocketDisconnect(Sender: TObject; Socket: TSocket);
procedure MBSocketDataArrive(Sender: TObject; Socket: TSocket);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
2楼: { Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
//
// 清提⽰区...
procedure TForm1.Button1Click(Sender: TObject);
begin
memo1.Lines.Clear;
end;
//
// 退出程序...
procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;
//
// 连接服务器...
procedure TForm1.Button3Click(Sender: TObject);
begin
try
mbsocket.Open;
except
on e:exception do
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>连接服务器失
败!'+e.ClassName+'-'+e.Message);
end;
end;
//
// 发送数据...
procedure TForm1.Button4Click(Sender: TObject);
var
tmpstr: string;
data: TBytes;
begin
tmpstr:=memo2.Lines.Text;
Data:=TEncoding.Convert(TEncoding.Default,TEncoding.GetEncoding(936),bytesof(tmpstr)); memo1.Lines.Add('');
if MBSocket.SendBuff(@Data[0],length(Data)) then
begin
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>发送数据到服务器成功:');
memo1.Lines.Add(tmpstr);
end
else
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>发送数据到服务器失败!')
end;
//
// 断开...
procedure TForm1.Button5Click(Sender: TObject);
begin
MBSocket.Close;
//
// 连接成功的事件...
procedure TForm1.MBSocketConnect(Sender: TObject; Socket: TSocket);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <-- 连接服务器成功!');
end;
//
// 收到数据的事件,接收数据并显⽰...
procedure TForm1.MBSocketDataArrive(Sender: TObject; Socket: TSocket);
var
j: integer;
tmpstr: string;
data: TBytes;
begin
//
// 取待接收数据的长度...
j:=MBSocket.DataLength;
//
// 接收数据到缓冲区...
setlength(data,j);
MBSocket.ReceiveData(@data[0],j);
//
// 显⽰数据...
tmpstr:=StringOf(TEncoding.Convert(TEncoding.GetEncoding(936),TEncoding.Default,Data)); memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <-- 共有'+inttostr(j)+'字节的数据送达:'); memo1.Lines.Add(tmpstr);
end;
//
// 断开事件...
procedure TForm1.MBSocketDisconnect(Sender: TObject; Socket: TSocket);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <-- 与服务器断开了!');
end;
//
// 通信错误...
procedure TForm1.MBSocketError(Sender: TObject; Socket: TSocket;
const Error: string; var CanClose: Boolean);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <-- 发⽣了通信错误:'+error);
CanClose:=false;
end;
end.
此帖⼦包含附件:
JPEG 图像
⼤⼩:161.4K
----------------------------------------------
樵夫的⼤马甲
作者: jopher3 (樵夫的马六甲)▲▲△△△
-
注册会员
2017-1-22
12:46:58
3楼:四、结束语
通过测试,我们发现这种⽅法完全⽀持跨平台及长连接,异步效果也不错!在此,为EMB公司点个赞!⾮常给⼒!
然后,我们在TMBSocket基础上,实现真正的即时通信、结合Service实现⼿
然后,我们在TMBSocket基础上,实现真正的即时通信、结合Service实现⼿
机消息推送等,就变得轻⽽易举的了。

杠杆给你了,撬地球吧!

Delphi
移动开发准备的跨平台异步Socket 浏
览:650
加⼊我的收藏
楼主:⼀、引⾔
在D10.1 Berlin之前,Delphi移动开发⼀直缺少⼀个使⽤⽅便、跨平台的异步socket控件,除了Indy组件,连最基本的socket单元都缺少。

所以,移动开发时实现移动客户端和电脑服务器之间、⼿机之间的异步通信⽐较困难。

本⼈以前在实现⼿机端的消息传输时,还是通过HTTP轮询形式实现,响应速度慢、服务端压⼒⼤,不适合⼤并发即时通信开发。

D10.1 Berlin版本发布之后,这样的局⾯改观了,因为Berlin中提供了⼀个跨平台Socket单元,尽管不是异步的,但是,通过我们通过使⽤多线程等技术的再度封装,就可以实现异步通信——收到消息、连通、断开、出错等,都激发相应的事件。

本⼈近⽇就为QuickBurro中间件的移动开发组件增加了⼀个跨平台的异步Socket控
件: TMBSocket。

下⾯的代码是类声明,后图⽰意其属性、事件:
type
TConnectedEvent = procedure(Sender: TObject; Socket: TSocket) of object;
TDisconnectedEvent = procedure(Sender: TObject; Socket: TSocket) of Object;
TDataArrivedEvent = procedure(Sender: TObject; Socket: TSocket) of Object;
TErrorEvent = procedure(Sender: TObject; Socket: TSocket; const Error: string; var CanClose: boolean) of Object; //
TMBSocket=class(TComponent)
private
RawSocket: TSocket;
fHostName: string;
fHostAddress: string;
fPort: integer;
fActive: boolean;
fConnected: boolean;
//
fOnConnect: TConnectedEvent;
fOnDisconnect: TDisconnectedEvent;
fOnDataArrive: TDataArrivedEvent;
fOnError: TErrorEvent;
//
procedure SetHostName(aHostName: string);
procedure SetHostAddress(aHostAddress: string);
procedure SetPort(aPort: integer);
procedure SetActive(aActive: boolean);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy(); override;
procedure Open;
procedure Close;
function SendBuff(const BufferPtr: pointer; const DataLength: integer): boolean;
procedure ReceiveData(const BufferPtr: pointer; const Bytes: integer);
function DataLength(): integer;
published
property HostName: string read fHostName write SetHostName;
property HostAddress: string read fHostAddress write SetHostAddress;
property Port: integer read fPort write SetPort;
property Active: boolean read fActive write SetActive;
property Connected: boolean read fConnected;
//
property OnConnect: TConnectedEvent read fOnConnect write fOnConnect;
property OnDisconnect: TDisconnectedEvent read fOnDisconnect write fOnDisconnect;
property OnDataArrive: TDataArrivedEvent read fOnDataArrive write fOnDataArrive; property OnError: TErrorEvent read fOnError write fOnError;
End;
此帖⼦包含附件:
PNG 图像
⼤⼩:21.1K
----------------------------------------------
樵夫的⼤马甲
作者: jopher3 (樵夫的马六甲)▲▲△△△
-
注册会员
2017-1-22
12:46:11
⼆、电脑端服务程序
为了测试⼿机端TMBSocket控件的异步通信效果,我们先⽤TServerSocket快速搭建⼀个测试服务器,让它与⼿机端程序进⾏通信。

下⾯是代码和运⾏效果:
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, BurroSocket;
type
TForm1 = class(TForm)
Memo1: TMemo;
Label1: TLabel;
Edit1: TEdit;
Server: TBServerSocket;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Memo2: TMemo;
procedure Button4Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure ServerListen(Sender: TObject; Socket: TBCustomWinSocket);
procedure ServerClientRead(Sender: TObject; Socket: TBCustomWinSocket);
procedure ServerClientConnect(Sender: TObject; Socket: TBCustomWinSocket); procedure ServerClientDisconnect(Sender: TObject;
Socket: TBCustomWinSocket);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//
// 开启服务...
procedure TForm1.Button1Click(Sender: TObject);
begin
1楼: server.Port:=strtoint(edit1.Text);
server.Active:=true;
end;
//
// 停⽌服务...
procedure TForm1.Button3Click(Sender: TObject);
begin
server.Active:=false;
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>服务器顺利停⽌服务。

'); end;
//
// 客户端连上来时...
procedure TForm1.ServerClientConnect(Sender: TObject;
Socket: TBCustomWinSocket);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <--有客户端连上来
了!IP='+string(Socket.RemoteAddress));
end;
//
// 客户端断开时...
procedure TForm1.ServerClientDisconnect(Sender: TObject;
Socket: TBCustomWinSocket);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <--有客户端断开
了!IP='+string(Socket.RemoteAddress));
end;
//
// 客户端数据送达时...
procedure TForm1.ServerClientRead(Sender: TObject; Socket: TBCustomWinSocket); var
j: integer;
tmpstr: ansistring;
begin
j:=socket.ReceiveLength;
setlength(tmpstr,j);
Socket.ReceiveBuf(tmpstr[1],j);
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <--收到'+inttostr(j)+'个字节:'); memo1.Lines.Add(string(tmpstr));
end;
//
// 向第⼀个客户端连接发送测试数据...
procedure TForm1.Button2Click(Sender: TObject);
var
tmpstr: ansistring;
begin
tmpstr:=ansistring(memo2.Lines.Text);
server.Socket.Connections[0].SendBuf(tmpstr[1],length(tmpstr));
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>向客户端发送了如下消息:'); memo1.Lines.Add(string(tmpstr));
end;
//
// 服务端⼝开始⼯作时...
procedure TForm1.ServerListen(Sender: TObject; Socket: TBCustomWinSocket);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>服务器已启动,请⼿机端开始测试!');
end;
//
// 退出程序...
procedure TForm1.Button4Click(Sender: TObject);
begin
close;
end;
end.
此帖⼦包含附件:
PNG 图像
⼤⼩:6.8K
----------------------------------------------
樵夫的⼤马甲
作者: jopher3 (樵夫的马六甲)▲▲△△△
-
注册会员
2017-1-22 12:46:42
三、移动端异步通信测试程序
万事具备,我们来编写个⼿机端的异步通信客户端程序,让它与上⾯的简易测试服务器进⾏通信。

下⾯是测试程序源码、运⾏效果图:
unit main;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, .socket,
FMX.Objects, FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo,
MBSocket;
type
TForm1 = class(TForm)
Memo1: TMemo;
Rectangle1: TRectangle;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Rectangle2: TRectangle;
Label1: TLabel;
Button2: TButton;
Image1: TImage;
Memo2: TMemo;
MBSocket: TMBSocket;
Button1: TButton;
Image2: TImage;
StyleBook1: TStyleBook;
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure MBSocketConnect(Sender: TObject; Socket: TSocket);
procedure MBSocketError(Sender: TObject; Socket: TSocket;
const Error: string; var CanClose: Boolean);
procedure MBSocketDisconnect(Sender: TObject; Socket: TSocket);
procedure MBSocketDataArrive(Sender: TObject; Socket: TSocket);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
2楼: { Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
//
// 清提⽰区...
procedure TForm1.Button1Click(Sender: TObject);
begin
memo1.Lines.Clear;
end;
//
// 退出程序...
procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;
//
// 连接服务器...
procedure TForm1.Button3Click(Sender: TObject);
begin
try
mbsocket.Open;
except
on e:exception do
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>连接服务器失
败!'+e.ClassName+'-'+e.Message);
end;
end;
//
// 发送数据...
procedure TForm1.Button4Click(Sender: TObject);
var
tmpstr: string;
data: TBytes;
begin
tmpstr:=memo2.Lines.Text;
Data:=TEncoding.Convert(TEncoding.Default,TEncoding.GetEncoding(936),bytesof(tmpstr)); memo1.Lines.Add('');
if MBSocket.SendBuff(@Data[0],length(Data)) then
begin
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>发送数据到服务器成功:');
memo1.Lines.Add(tmpstr);
end
else
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': ==>发送数据到服务器失败!')
end;
//
// 断开...
procedure TForm1.Button5Click(Sender: TObject);
begin
MBSocket.Close;
end;
//
// 连接成功的事件...
procedure TForm1.MBSocketConnect(Sender: TObject; Socket: TSocket);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <-- 连接服务器成功!');
end;
//
// 收到数据的事件,接收数据并显⽰...
procedure TForm1.MBSocketDataArrive(Sender: TObject; Socket: TSocket);
var
j: integer;
tmpstr: string;
data: TBytes;
begin
//
// 取待接收数据的长度...
j:=MBSocket.DataLength;
//
// 接收数据到缓冲区...
setlength(data,j);
MBSocket.ReceiveData(@data[0],j);
//
// 显⽰数据...
tmpstr:=StringOf(TEncoding.Convert(TEncoding.GetEncoding(936),TEncoding.Default,Data)); memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <-- 共有'+inttostr(j)+'字节的数据送达:'); memo1.Lines.Add(tmpstr);
end;
//
// 断开事件...
procedure TForm1.MBSocketDisconnect(Sender: TObject; Socket: TSocket);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <-- 与服务器断开了!');
end;
//
// 通信错误...
procedure TForm1.MBSocketError(Sender: TObject; Socket: TSocket;
const Error: string; var CanClose: Boolean);
begin
memo1.Lines.Add('');
memo1.Lines.Add(formatdatetime('hh:nn:ss',now)+': <-- 发⽣了通信错误:'+error);
CanClose:=false;
end;
end.
此帖⼦包含附件:
JPEG 图像
⼤⼩:161.4K
----------------------------------------------
樵夫的⼤马甲
作者: jopher3 (樵夫的马六甲)▲▲△△△
-
注册会员
2017-1-22
12:46:58
3楼:四、结束语
通过测试,我们发现这种⽅法完全⽀持跨平台及长连接,异步效果也不错!在此,为EMB公司点个赞!⾮常给⼒!
然后,我们在TMBSocket基础上,实现真正的即时通信、结合Service实现⼿机消息推送等,就变得轻⽽易举的了。

杠杆给你了,撬地球吧!
机消息推送等,就变得轻⽽易举的了。

杠杆给你了,撬地球吧!。

相关文档
最新文档