Сквозной прокси, использующий TServerSocket, имеет неполный код - PullRequest
0 голосов
/ 28 октября 2019

У меня есть программное обеспечение удаленной регистрации, где клиентское приложение, использующее TClientSocket, подключается к серверному приложению, использующему TServerSocket (оба TServerSocket и ClientSocket находятся в режиме неблокируемый ).

Соединение работает нормально (так как эта DMZ включена на модеме на стороне сервера), и сервер может получать / отправлять данные клиенту.

Теперь я хочу, чтобы все могли работать таким же образом, но на этот раз с помощью сквозного прокси-программного обеспечения, которое я могу запустить на облачном компьютере (например, Windows VPS), и клиент сначала может подключиться к нему. и от он к серверу.

enter image description here

После нескольких часов поиска в сети я наконец-то нашел этот пример кода, который, вероятно, может работатьв моем случае, но отсутствуют некоторые элементы пользовательских классов, созданных, между другими вещами.

Как это исправить? См .:

enter image description here

 uses
  System.Win.ScktComp;

type
  TMyBuffer = class(TMemoryStream)
  private
    FSocket: TCustomWinSocket;
  public
    constructor Create(ASocket: TCustomWinSocket);
    procedure Send(Data: Pointer; DataLen: Integer);
    procedure Flush;
  end;

  TMyServerSocketData = class;

  TMyClientSocket = class
  private
    FBuffer: TMyBuffer;
    FServerSocketData: TMyServerSocketData;
  protected
    procedure Event(Socket: TCustomWinSocket; SocketEvent: TSocketEvent); override;
    procedure Error(Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); override;
  public
    constructor Create(AServerSocketData: TMyServerSocketData); reintroduce;
    destructor Destroy; override;
    procedure Send(Data: Pointer; DataLen: Integer);
    property ServerSocketData: TMyServerSocketData read FServerSocketData;
  end;

  TMyServerSocketData = class
  private
    FBuffer: TMyBuffer;
    FClientSocket: TMyClientSocket;
    FServerSocket: TCustomWinSocket;
  public
    constructor Create(AServerSocket: TCustomWinSocket);
    destructor Destroy; override;
    procedure Send(Data: Pointer; DataLen: Integer);
    procedure FlushBuffer;
    property ClientSocket: TMyClientSocket read FClientSocket;
  end;

type
  TFProxy = class(TForm)
    ServerSocket1: TServerSocket;
    procedure FormCreate(Sender: TObject);
    procedure ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure ServerSocket1ClientWrite(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FProxy: TFProxy;

implementation

{$R *.dfm}

constructor TMyBuffer.Create(ASocket: TCustomWinSocket);
begin
  inherited Create;
  FSocket := ASocket;
end;

procedure TMyBuffer.Send(Data: Pointer; DataLen);
var
  PData: PByte;
  NumSent: Integer;
begin
  PData := PByte(Data);
  if Self.Size = 0 then
  begin
    repeat
      NumSent := FSocket.SendBuf(PData^, DataLen);
      if NumSent < 1 then
        Break;
      Inc(PData, NumSent);
      Dec(DataLen, NumSent);
    until DataLen = 0;
  end;
  if DataLen > 0 then
  begin
    Self.Seek(0, soEnd);
    Self.WriteBuffer(PData^, DataLen);
  end;
end;

procedure TMyBuffer.Flush;
var
  PData: PByte;
  DataLen, NumSent: Integer;
begin
  if Self.Size = 0 then
    Exit;
  Self.Position := 0;
  PData := PByte(Self.Memory);
  DataLen := Self.Size;
  repeat
    NumSent := FSocket.SendBuf(PData^, DataLen);
    if NumSent < 1 then
      Break;
    Inc(PData, NumSent);
    Dec(DataLen, NumSent);
    Self.Seek(NumSent, soCurrent);
  until DataLen = 0;
  if Self.Position = 0 then
    Exit;
  if Self.Position = Self.Size then
    Self.Clear
  else
  begin
    Move(PData, Self.Memory, DataLen);
    Self.Size := DataLen;
  end;
end;

constructor TMyClientSocket.Create(AServerSocketData: TMyServerSocketData);
begin
  inherited Create(nil);
  ClientType := ctNonBlocking;
  FBuffer := TMyBuffer.Create(Socket);
  FServerSocketData := AServerSocketData;
end;

destructor TMyClientSocket.Destroy;
begin
  FBuffer.Free;
  inherited;
end;

procedure TMyClientSocket.Send(Data: Pointer; DataLen: Integer);
begin
  FBuffer.Send(Data, DataLen);
end;

procedure TMyClientSocket.Event(Socket: TCustomWinSocket; SocketEvent: TSocketEvent);
var
  Buf: array[0..1023] of byte;
  BufLen, NumSent: Integer;
  PBuf: PByte;
begin
  case SocketEvent of
    seRead:
      begin
        if not FServerSocketData.ServerSocket.Connected then
          Exit;
        BufLen := Socket.ReceiveBuf(Buf[0], SizeOf(Buf));
        if BufLen > 0 then
          FServerSocketData.Send(@Buf[0], BufLen);
      end;
    seWrite:
      FBuffer.Flush;
  else
    inherited;
  end;
end;

procedure TMyClientSocket.Error(Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  FServerSocketData.ServerSocket.Close;
  inherited;
end;

constructor TMyServerSocketData.Create(AServerSocket: TCustomWinSocket);
begin
  inherited;
  FBuffer := TMyBuffer.Create(AServerSocket);
  FClientSocket := TMyClientSocket.Create(Self);
  FServerSocket := AServerSocket;
end;

destructor TMyServerSocketData.Destroy;
begin
  FBuffer.Free;
  FClientSocket.Free;
  inherited;
end;

procedure TMyServerSocketData.Send(Data: Pointer; DataLen: Integer);
begin
  FBuffer.Send(Data, DataLen);
end;

procedure TMyServerSocketData.FlushBuffer;
begin
  FMyBuffer.Flush;
end;

procedure TFProxy.FormCreate(Sender: TObject);
begin
  ServerSocket1.OnClientConnect := ServerSocket1ClientConnect;
  ServerSocket1.OnClientDisconnect := ServerSocket1ClientDisconnect;
  ServerSocket1.OnClientRead := ServerSocket1ClientRead;
  ServerSocket1.Port := 80;
  ServerSocket1.ServerType := stNonBlocking;
  ServerSocket1.Active := true;
end;

procedure TFProxy.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
var
  Data: TMyServerSocketData;
begin
  Data := TMyServerSocketData.Create(Socket);
  try
    Data.ClientSocket.Host := '192.168.69.1';
    Data.ClientSocket.Port := 80;
    Data.ClientSocket.Open;
  except
    Data.Free;
    raise;
  end;
  Socket.Data := Data;
end;

procedure TFProxy.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  TMyServerSocketData(Socket.Data).Free;
end;

procedure TFProxy.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  ClientSocket: TMyClientSocket;
  Buf: array[0..1023] of byte;
  BufLen: Integer;
begin
  ClientSocket := TMyServerSocketData(Socket.Data).ClientSocket;
  if not ClientSocket.Socket.Connected then
    Exit;
  BufLen := Socket.ReceiveBuf(Buf[0], SizeOf(Buf));
  if BufLen > 0 then
    ClientSocket.Send(@Buf[0], BufLen);
end;

procedure TFProxy.ServerSocket1ClientWrite(Sender: TObject; Socket: TCustomWinSocket);
begin
  TMyServerSocketData(Socket.Data).FlushBuffer;
end;

end.
...