这是试图通过收到的费用来重新定义my previous question。
我想要一个简单的网络通信,我可以将其用作底层框架,而不必再看一遍。我只想将一个字符串从一台PC推到另一台PC并获得响应字符串。我不想担心打开连词,保持开放,如果他们关闭就重新打开等等。
我想专注于我的应用程序,并提供一个简单的功能API:
SendStringToOtherPc() : String; // Called at PC #1.
// Returns PC #2's result string
// or "" on error (or throws exception)
ProcessReceivedStringAndReply(); // Called at PC # 2. Sends result string
我认为那些拥有多个项目的人拥有一个“启动”框架,他们将这些框架用于每个新项目,只需添加特定于应用程序的日志 - 这就是我想要的框架或抽象层。任何人都可以指点我的URL吗?
我对套接字编程一无所知,也没有时间学习。如果我这样做,其他一些项目将受到影响。
虽然我确实尊重我应该理解我的软件正在做什么的论点,但是有一个有效的反驳论证,每个人都不应该为自己开发这个特定的轮子,而且肯定有一些FOSS围绕着哪个我做什么要什么?
提前致谢。
更新:我似乎开始有点争议,有些人认为我懒惰或注定要发生灾难。所以,也许我应该解释一下我的历史。
我花了三十年时间开发电信软件,我们始终遵循OSI 7 layer model。我一般是第3层,网络层,无论是电话交换机,基站还是hanset,无论协议是ISDN,ISUP,DECT,GSM,GPRS,UMTS还是专有的卫星协议,我都可以随时设置第2层的Serveice接入点,数据传输层,“嘿,你!把这个消息传给另一个人并告诉我他的回复是什么”。我知道它是怎么做的吗?我在乎吗?
@CosmicPrund,除非有人指出我在第2层,否则他可能会得到答案,说“这个问题的真正答案是你所需要的只是学习如何使用Indy”而且我不同意。有人会,但如果我可以帮助的话,不是我。我已经倾斜了太多的技能,编程语言,数据库系统,操作系统,并且如果可以的话,我将总是避免学习更多关于另一个的概述。就像艾萨克·牛顿爵士一样,我更愿意站在巨人的肩膀上。
软件对一个人来说太大了。当然没有人从头开始每个项目?我猜你重用了之前项目的网络代码(?),可重用的代码是我的“第2层”。我的问题是,在哪里可以下载这些代码并使用它而不了解其内部工作原理?
有谁知道这样的事情?
答案:我用了Indy并得到了我想要的东西。我将尝试建立一个可以用作网络抽象层的函数库。
答案 0 :(得分:4)
我有一个免费的框架可以做到这一切。好处是你可以在不知道套接字的情况下使用它。您可以安全地忽略连接和断开连接,因为这全部由框架处理(底层的通信框架通过可配置的ping保持连续连接等)。消息队列线程模型也内置在框架中。我也有一个演示您的确切示例。缺点显然是陡峭的学习曲线。看看http://www.csinnovations.com/framework_delphi.htm
答案 1 :(得分:3)
这个问题的真正答案是你需要的只是学习如何使用Indy。为了证明我的观点,我会给你一个89行的单位,实际上实现你所要求的一切,以及如何使用它的概念验证样本。
在我展示代码之前,我想提一下:
这是“框架”单位:
unit UTcpIntercom;
interface
uses IdContext, IdCustomTCPServer, IdTCPServer, IdBaseComponent,
IdComponent, IdTCPConnection, IdTCPClient, SysUtils;
type
EIntercomError = class(Exception);
TReceivedText = procedure(const TextFromClient:string; var Response:string) of object;
TReceivedTextProc = procedure(const TextFromClient:string; var Response:string);
TIntercomServer = class(TIdCustomTCPServer)
protected
Event: TReceivedText;
Proc: TReceivedTextProc;
HostGreeting: string;
public
function DoExecute(AContext: TIdContext): Boolean; override;
end;
function SendTextToComputer(const TextToSend, HostToSend, HostGreeting:string; PortNumber: Integer): string;
function StartServer(PortNumber:Integer; const HostGreeting:string; OnReceivedText: TReceivedText):TIntercomServer;overload;
function StartServer(PortNumber:Integer; const HostGreeting:string; OnReceivedText: TReceivedTextProc):TIntercomServer;overload;
implementation
function SendTextToComputer(const TextToSend, HostToSend, HostGreeting:string; PortNumber: Integer): string;
var Id: TIdTCPClient;
begin
Id := TIdTCPClient.Create(nil);
try
Id.Host := HostToSend;
Id.Port := PortNumber;
Id.Connect;
try
if Id.IOHandler.ReadLn <> HostGreeting then
raise EIntercomError.Create('Host is invalid: ' + HostToSend);
Id.IOHandler.WriteLn(TextToSend);
Result := Id.IOHandler.ReadLn;
Id.Disconnect;
finally Id.Disconnect;
end;
finally Id.Free;
end;
end;
function StartServer(PortNumber:Integer; const HostGreeting:string; OnReceivedText: TReceivedText):TIntercomServer;overload;
begin
Result := TIntercomServer.Create(nil);
Result.Bindings.Add.Port := PortNumber;
Result.HostGreeting := HostGreeting;
Result.Event := OnReceivedText;
Result.Active := True;
end;
function StartServer(PortNumber:Integer; const HostGreeting:string; OnReceivedText: TReceivedTextProc):TIntercomServer;overload;
begin
Result := TIntercomServer.Create(nil);
Result.Bindings.Add.Port := PortNumber;
Result.HostGreeting := HostGreeting;
Result.Proc := OnReceivedText;
Result.Active := True;
end;
{ TIntercomServer }
function TIntercomServer.DoExecute(AContext: TIdContext): Boolean;
var Text, Response: string;
begin
AContext.Connection.IOHandler.WriteLn(HostGreeting);
Text := AContext.Connection.IOHandler.ReadLn;
Response := '';
if Assigned(Event) then
Event(Text, Response)
else if Assigned(Proc) then
Proc(Text, Response)
else
Response := 'No handler assigned.';
AContext.Connection.IOHandler.WriteLn(Response);
AContext.Connection.Disconnect;
Result := True;
end;
end.
这是使用该单元的代码。请注意DoSomethingWithTextFromClient
,这基本上是您的ProcessReceivedStringAndReply
方法。另请注意使用StartServer
和SendTextToComputer
。
program Project9;
{$APPTYPE CONSOLE}
uses
SysUtils,
UTcpIntercom in 'UTcpIntercom.pas';
procedure DoSomethingWithTextFromClient(const TextFromClient: string; var Response:string);
var i: Integer;
C: Char;
Len: Integer;
begin
Response := TextFromClient;
Len := Length(Response);
for i:=1 to (Length(Response) div 2) do
begin
C := Response[Len-i+1];
Response[Len-i+1] := Response[i];
Response[i] := C;
end;
end;
begin
try
try
with StartServer(1000, 'Test', @DoSomethingWithTextFromClient) do
begin
WriteLn(SendTextToComputer('12345678', '127.0.0.1', 'Test', 1000));
Free;
end;
Readln;
except on E:Exception do
begin
WriteLn(E.ClassName);
WriteLn(E.Message);
Readln;
end;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.