Indy TCP套接字可以在两个线程之间共享吗



我想要一个连接,在这个连接中,两个终端都在等待读取命令,并不时地向另一个发送一些数据。当然,我知道如何实现我的协议,但如果我执行Socket.ReadUInt32,它将阻塞我的执行路径,并且我无法在需要时发送命令。所以我想,如果我使用同一个套接字从另一个线程发送命令呢?我写了一个最小的例子。。。而且它似乎在起作用。但我不确定这是正确的做法,还是这次运气好。。。这种技术可靠吗?额外的线程将使用套接字来发送UInt32值,以唤醒另一端,然后,连接将在主线程中进行。

unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, IdTCPConnection,
IdTCPClient, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer,
IdContext, IdThreadComponent;
const
WM_LOGEVENT = WM_USER + 1;
type
TForm1 = class(TForm)
Server: TIdTCPServer;
Client: TIdTCPClient;
BStartServer: TButton;
BConnectClient: TButton;
ClientWriteThread: TIdThreadComponent;
Memo: TMemo;
BSendCommand: TButton;
ClientReadThread: TIdThreadComponent;
procedure BStartServerClick(Sender: TObject);
procedure ServerExecute(AContext: TIdContext);
procedure BConnectClientClick(Sender: TObject);
procedure ClientWriteThreadRun(Sender: TIdThreadComponent);
procedure BSendCommandClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ClientReadThreadRun(Sender: TIdThreadComponent);
private
procedure LogEvent(var Msg: TMessage); message WM_LOGEVENT;
procedure SendEvent(const Msg: String);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.LogEvent(var Msg: TMessage);
var PStr: PString;
begin
PStr:= PString(Msg.WParam);
Memo.Lines.Add(Copy(PStr^, 1, Length(PStr^)));
end;
procedure TForm1.SendEvent(const Msg: String);
begin
SendMessage(Handle, WM_LOGEVENT, WPARAM(@Msg), 0);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Server.Bindings.Clear;
Server.Bindings.Add.SetBinding('192.168.0.3', 60200);
Client.Host:= '192.168.0.3';
Client.Port:= 60200;
end;
procedure TForm1.BStartServerClick(Sender: TObject);
begin
Server.Active:= True;
Caption:= IntToStr(Byte(Server.Active));
end;
procedure TForm1.BConnectClientClick(Sender: TObject);
begin
Client.Connect;
ClientReadThread.Start;
end;
procedure TForm1.BSendCommandClick(Sender: TObject);
begin
ClientWriteThread.Start;
end;
procedure TForm1.ClientWriteThreadRun(Sender: TIdThreadComponent);
var Data: Cardinal;
begin
Data:= 1234;
SendEvent('Client send: '+ IntToStr(Data));
Client.Socket.Write(Data);
Sender.Terminate;
end;
procedure TForm1.ClientReadThreadRun(Sender: TIdThreadComponent);
var Data: Cardinal;
begin
SendEvent('Client listening...');
Data:= Client.Socket.ReadUInt32;
SendEvent('Client received: '+ IntToStr(Data));
Client.Disconnect;
SendEvent('Client stopped.');
Sender.Terminate;
end;
procedure TForm1.ServerExecute(AContext: TIdContext);
var Data: Cardinal;
Srv: String;
begin
Srv:= 'Server '+IntToStr(Random(100));
SendEvent(Srv+' listening...');
Data:= AContext.Connection.Socket.ReadUInt32;
SendEvent(Srv+' received: '+IntToStr(Data));
Data:= 9999;
SendEvent(Srv+' Send: '+IntToStr(Data));
AContext.Connection.Socket.Write(Data);
AContext.Connection.Disconnect;
SendEvent(Srv+' stopped.');
end;
end.

是的,在一个线程中发送连接,同时在另一个线程读取同一连接是安全的。套接字具有用于入站和出站数据的独立内部缓冲区。

只需确保在不同步访问连接的情况下,不会尝试同时从两个线程发送,或同时从这两个线程读取。

最新更新