Как подключить клиентское приложение к серверному приложению, проходя через третье приложение, размещенное на VPS (виртуальный частный сервер)? - PullRequest
4 голосов
/ 24 октября 2019

У меня есть клиент> серверное приложение, где устанавливаются соединения с использованием компонентов Socket (TClientSocket клиента подключается к TServerSocket сервера). Теперь я хочу, чтобы клиенты сначала подключались к третьему приложению (своего рода «мост соединения» или «повторитель»), которое будет работать в Windows VPS и должно направлять подключения этих клиентов к серверному приложению, запущенному на серверном ПК. Пример:

enter image description here

Возможно (я не уверен) этот тип "моста соединения" или "повторителя", который будет работать на VPS, может быть похож насерверное приложение, которое будет работать на серверном ПК, но я не знаю, как подключаться и осуществлять управление подключением / отключением и отправкой / получением данных между этими тремя приложениями. Кто-то может сказать мне, как это можно сделать простым способом, и, если возможно, также привести пример кода об этом?

Ниже следует код клиента и сервера (сервер, который будет работать на сервере ПК), это всечто у меня есть до сих пор.

Клиент:

uses
  ScktComp;

type
  TForm1 = class(TForm)
    ClientSocket1: TClientSocket;
    Timer1: TTimer;
    Label1: TLabel;
    procedure ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientSocket1Connecting(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure Timer1Timer(Sender: TObject);
    procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
  Label1.Caption := 'CONNECTED';
end;

procedure TForm1.ClientSocket1Connecting(Sender: TObject; Socket: TCustomWinSocket);
begin
  Label1.Caption := 'CONNECTING...';
end;

procedure TForm1.ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  Label1.Caption := 'DISCONNECTED';
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if not ClientSocket1.Active then
    ClientSocket1.Active := true;
end;

procedure TForm1.ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  ErrorCode := 0;
end;

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
  s: string;
begin
  s := Socket.ReceiveText;
  if s = 'CMD' then
    Socket.SendText('Hello, here is Client: ' + Socket.LocalHost + '!');
end;

end.

Сервер:

uses
  ScktComp;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    ServerSocket1: TServerSocket;
    PopupMenu1: TPopupMenu;
    SON: TMenuItem;
    SOFF: TMenuItem;
    SCMD: TMenuItem;
    procedure ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ServerSocket1ClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure SONClick(Sender: TObject);
    procedure SOFFClick(Sender: TObject);
    procedure SCMDClick(Sender: TObject);
    procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
var
  Item: TListItem;
begin
  Item := ListView1.Items.Add;
  Item.Caption := IntTostr(Socket.Handle);
  Item.SubItems.Add(Socket.RemoteAddress);
  Item.SubItems.Add(Socket.RemoteHost);
  Item.Data := Socket.Data;
end;

procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
var
  Item: TListItem;
begin
  Item := ListView1.FindCaption(0, inttostr(Socket.Handle), false, true, false);
  if Item <> nil then
    Item.Delete;
end;

procedure TForm1.ServerSocket1ClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  ErrorCode := 0;
end;

procedure TForm1.SONClick(Sender: TObject);
begin
  ServerSocket1.Active := true;
end;

procedure TForm1.SOFFClick(Sender: TObject);
begin
  ServerSocket1.Active := false;
end;

procedure TForm1.SCMDClick(Sender: TObject);
begin
  if ListView1.Selected = nil then
    exit;
  ServerSocket1.Socket.Connections[ListView1.ItemIndex].SendText('CMD');
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  s: string;
begin
  s := Socket.ReceiveText;
  if s <> '' then
    ShowMessage(s);
end;

end.

ВЫПУСК:

Этот вопрос был решен с помощью этого вопроса / ответа. Спасибо @ afarah по точкам в правильном направлении (прокси-сервер): D.

...