寻求(免费)网络编程框架

时间:2012-01-19 05:14:26

标签: delphi network-programming

这是试图通过收到的费用来重新定义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
  • 我确实需要知道其他PC是否回复了;如果是的话,结果字符串是什么
  • 同样“很高兴”也可以让两台PC发起通信。如果没有,我可以拥有其中一个(客户端民意调查),或让另一个发送其通信作为对我需要添加的心跳的回复。

我认为那些拥有多个项目的人拥有一个“启动”框架,他们将这些框架用于每个新项目,只需添加特定于应用程序的日志 - 这就是我想要的框架或抽象层。任何人都可以指点我的URL吗?

我对套接字编程一无所知,也没有时间学习。如果我这样做,其他一些项目将受到影响。

虽然我确实尊重我应该理解我的软件正在做什么的论点,但是有一个有效的反驳论证,每个人都不应该为自己开发这个特定的轮子,而且肯定有一些FOSS围绕着哪个我做什么要什么?

提前致谢。


更新:我似乎开始有点争议,有些人认为我懒惰或注定要发生灾难。所以,也许我应该解释一下我的历史。

我花了三十年时间开发电信软件,我们始终遵循OSI 7 layer model。我一般是第3层,网络层,无论是电话交换机,基站还是hanset,无论协议是ISDN,ISUP,DECT,GSM,GPRS,UMTS还是专有的卫星协议,我都可以随时设置第2层的Serveice接入点,数据传输层,“嘿,你!把这个消息传给另一个人并告诉我他的回复是什么”。我知道它是怎么做的吗?我在乎吗?

@CosmicPrund,除非有人指出我在第2层,否则他可能会得到答案,说“这个问题的真正答案是你所需要的只是学习如何使用Indy”而且我不同意。

有人会,但如果我可以帮助的话,不是我。我已经倾斜了太多的技能,编程语言,数据库系统,操作系统,并且如果可以的话,我将总是避免学习更多关于另一个的概述。就像艾萨克·牛顿爵士一样,我更愿意站在巨人的肩膀上。

软件对一个人来说太大了。当然没有人从头开始每个项目?我猜你重用了之前项目的网络代码(?),可重用的代码是我的“第2层”。我的问题是,在哪里可以下载这些代码并使用它而不了解其内部工作原理?

有谁知道这样的事情?


答案:我用了Indy并得到了我想要的东西。我将尝试建立一个可以用作网络抽象层的函数库。

2 个答案:

答案 0 :(得分:4)

我有一个免费的框架可以做到这一切。好处是你可以在不知道套接字的情况下使用它。您可以安全地忽略连接和断开连接,因为这全部由框架处理(底层的通信框架通过可配置的ping保持连续连接等)。消息队列线程模型也内置在框架中。我也有一个演示您的确切示例。缺点显然是陡峭的学习曲线。看看http://www.csinnovations.com/framework_delphi.htm

答案 1 :(得分:3)

这个问题的真正答案是你需要的只是学习如何使用Indy。为了证明我的观点,我会给你一个89行的单位,实际上实现你所要求的一切,以及如何使用它的概念验证样本。

在我展示代码之前,我想提一下:

  • 89行代码不能称为框架。它只是一个薄的包装,根本不值得。迟早你会遇到需要直接访问底层Indy框架的东西。
  • 拥有更多Indy经验的人可能会使用更少的代码行来写这个。
  • 我自己甚至可以缩短它,因为我包含两个重载的“StartServer”方法以便于演示。
  • 使用放在表单上的组件实现此操作会进一步减少行数。

这是“框架”单位:

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方法。另请注意使用StartServerSendTextToComputer

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.