Q:

Seeking (free) framework for network programming

This is an attempt to rephrase my previous question as a result of the feeedback which it received.
I want a simple network communication which I can use as an underlying framework and never have to look at again. I just want o push a string from one PC to another and get a string in response. I don't want to have to worry about opening conenctions, keeping them open, reopening them if they close, etc.
I want to concentrate on my application and have a simple functional API along the lines of:  
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

I do need to know if the other PC replied or not; and, if so, what the result string was
also "nice to have" would be for both PCs to initiate communication. If not, I can have one of them (the client poll), or have the other send its communication as a reply to the heartbeat which I need to add.

I presume that those with multiple fprojects under their belts have a "starter" framework which they use for every new project, just adding the application specific log - and it's such a framwork, or abstraction layer, that I want. Can anyone point me at a URL?
I know nothing of socket programming and don't really have time to learn. If I do, some other project will suffer.
While I do respect the argument that I should understand what my software is doing, there is a valid counter-arguement that everyone should not have to develop this particular wheel for himself, and surely there is some FOSS around which does what I want?
Thanks in advance.

Update: I seem to have started a little controversy, with some thinking me lazy or doomed to disaster. So, maybe I should explain a little of my history. 
I spent three decades developing telecoms software and we always followed the OSI 7 layer model. I was generally layer 3, the network layer, and no matter whether it was a telephone exchange, base station or hanset, whether the protocol was ISDN, ISUP, DECT, GSM, GPRS, UMTS or a propietary satellite protocol, I could always instuct a Serveice Access Point of Layer 2, the data transport layer, "hey, you! Get this mesage to the other guy and tell me what his reply is". Did I know how it was done? Did I care?
@CosmicPrund, who will probably be awarded the answer unless someone points me at a Layer 2, said "The true answer to this question is that all you need is learn how to use Indy" and I beg to disagree. 
Someone will, but not me if I can help it. I already leanred too many skills, programming languages, databse systems, oprerating systems and will always avoid learning more that an overview of another if I can. Like Sir Isaac Newton, I would prefer to stand on the shoulders of giants.
Software is just getting too big for one guy. Surely none of you start each project from scratch? I guess you reuse the networking code from a previous project(?) and that reusable code is my "Layer 2". And my question is where can I download such code and use it without understanding its inner workings?
Does anyone know of such a thing?

Answer: I used Indy and got what I wanted. I will porbably try to build up a library of functions which I can use as a network abstraction layer.

A:

I have a free framework that will do all this. The benefit is that you can use it without any knowledge of sockets whatsoever. You can safely ignore connects and disconnects because this is all handled by the framework (the underlying comms framework keeps a continuous connection via configurable pings, etc). A message queueing threading model is also built into the framework. I have a demo for your exact example as well. The downside is obviously a steep learning curve. Have a look at http://www.csinnovations.com/framework_delphi.htm

A:

The true answer to this question is that all you need is learn how to use Indy. To prove my point I'll give you a 89 lines unit that actually implements all you requested, plus a proof-of-concept sample of how to use it.
Before I show the code I'd like to mention:

89 lines of code can't be called a framework. It's just a thin wrapper that's simply not worth it. Sooner or later you'd run into stuff that requires direct access to the underlying Indy framework.
Someone with more Indy experience would probably write this using even less lines of code.
I could even make it shorter myself, since I included two overloaded "StartServer" methods for ease of demonstration.
Implementing this using components dropped on a form would cut the number of lines further.

Here's the "framework" unit:
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.

Here's the code that uses the unit. Notice the DoSomethingWithTextFromClient, that's essentially your ProcessReceivedStringAndReply method. Also notice the use of StartServer and 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.

