12.1. Ejemplo de comunicaciones TCP/IP chat

Formulario del ejemplo de Chat con Socket TCP/IP
Consideraciones:
Establecer un puerto de comunicaciones valido para el ClientSocket y el ServerSocket en Propiedades -> Port, por ejemplo el 1024.
Añadir al control StatusBar1 un Panel en Propiedades -> Panels -> Add New.
main.cpp
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "main.h"
//---------------------------------------------------------------------------
#pragma link "ScktComp"
#pragma resource "*.dfm"
TChatForm *ChatForm;
//---------------------------------------------------------------------------
__fastcall TChatForm::TChatForm(TComponent* Owner):TForm(Owner)
{
}
//---------------------------------------------------------------------------
// Activar el servidor de Socket e indicar el modo de escucha
//---------------------------------------------------------------------------
void __fastcall TChatForm::CheckBoxListenClick(TObject *Sender)
{
//CheckBoxListen->Checked = !CheckBoxListen->Checked;
if(CheckBoxListen->Checked){
ClientSocket->Active = false;
ServerSocket->Active = true;
StatusBar1->Panels->Items[0]->Text = "Listening...";
}else{
if(ServerSocket->Active){
ServerSocket->Active = false;
}
StatusBar1->Panels->Items[0]->Text = "";
}
}
//---------------------------------------------------------------------------
// Conectar con el servidor indicado
//---------------------------------------------------------------------------
void __fastcall TChatForm::ConnectClick(TObject *Sender)
{
// Si hay una conexión activa, se ha de cerrar antes de establecer una nueva
if(ClientSocket->Active){
ClientSocket->Active = false;
}
// Conectarse con el servidor
if(InputQuery("Computer to connect to", "Address Name:", Server)){ // Pedir la IP del servidor
if(Server.Length() > 0){
ClientSocket->Host = Server; // Especificar la IP al Host
ClientSocket->Active = true; // Conectar con el servidor
//CheckBoxListen->Checked = false; // Cerrar el servidor y salir del modo de escucha
// Si se para el servidor, no se puede realizar una conexión con localhost
}
}
}
//---------------------------------------------------------------------------
// Cerrar las comunicaciones y salir
//---------------------------------------------------------------------------
void __fastcall TChatForm::ExitClick(TObject *Sender)
{
ServerSocket->Close(); // Cerrar el servidor de Socket
ClientSocket->Close(); // Cerrar el cliente de Socket
Close(); // Salir del programa
}
//---------------------------------------------------------------------------
// Transmitir datos
//---------------------------------------------------------------------------
void __fastcall TChatForm::Memo1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
if(Key == VK_RETURN){ // Si se ha pulsado la tecla de retorno de carro
// Si actuamos como servidor, un cliente se ha conectado a nosotros
if(IsServer){
// Enviar la línea actual
ServerSocket->Socket->Connections[0]->SendText(Memo1->Lines->Strings[Memo1->Lines->Count - 1]);
}
// Si actuamos como cliente, nos conectamos a un servidor
else{
// Enviar la línea actual
ClientSocket->Socket->SendText(Memo1->Lines->Strings[Memo1->Lines->Count -1]);
}
}
}
//---------------------------------------------------------------------------
// Al arrancar el programa
//---------------------------------------------------------------------------
void __fastcall TChatForm::FormCreate(TObject *Sender)
{
CheckBoxListen->Checked = true; // Activar el Socket y entrar en modo de escucha
}
//---------------------------------------------------------------------------
// Al realizar la conexión
//---------------------------------------------------------------------------
void __fastcall TChatForm::ClientSocketConnect(TObject *Sender, TCustomWinSocket *Socket)
{
StatusBar1->Panels->Items[0]->Text = "Connect to: " + Socket->RemoteHost;
}
//---------------------------------------------------------------------------
// Parar o desconectar la conexión
//---------------------------------------------------------------------------
void __fastcall TChatForm::DisconnectClick(TObject *Sender)
{
ClientSocket->Active = false; // Cerrar la conexión con el servidor
ServerSocket->Active = true; // Activar el ServerSocket y entrar en modo de escucha
StatusBar1->Panels->Items[0]->Text = "Listening...";
}
//---------------------------------------------------------------------------
// Se produce cuando un socket de cliente debe leer la información de la conexión de socket.
//---------------------------------------------------------------------------
void __fastcall TChatForm::ClientSocketRead(TObject *Sender, TCustomWinSocket *Socket)
{
// Cuando el servidor envia datos al ciente y este los ha de procesar
Memo2->Lines->Add(Socket->ReceiveText()); // Añadir los datos al memo de recepción
}
//---------------------------------------------------------------------------
// Se produce cuando el socket de servidor debe leer la información de un socket cliente.
//---------------------------------------------------------------------------
void __fastcall TChatForm::ServerSocketClientRead(TObject *Sender, TCustomWinSocket *Socket)
{
// Cuando el cliente envia datos al servidor y este los ha de procesar
Memo2->Lines->Add(Socket->ReceiveText()); // Añadir los datos al memo de recepción
}
//---------------------------------------------------------------------------
// Se produce en un servidor de sockets inmediatamente después de aceptar la conexión a un socket de cliente.
//---------------------------------------------------------------------------
void __fastcall TChatForm::ServerSocketAccept(TObject *Sender, TCustomWinSocket *Socket)
{
IsServer = true; // Actuamos como servidor
StatusBar1->Panels->Items[0]->Text = "Connect to: " + Socket->RemoteAddress;
}
//---------------------------------------------------------------------------
// Se produce cuando un socket de cliente completa una conexión aceptada por el socket de servidor.
//---------------------------------------------------------------------------
void __fastcall TChatForm::ServerSocketClientConnect(TObject *Sender, TCustomWinSocket *Socket)
{
Memo2->Lines->Clear(); // Limpiar el memo de datos
}
//---------------------------------------------------------------------------
// Se produce justo antes de un socket de cliente cierra la conexión con un servidor.
//---------------------------------------------------------------------------
void __fastcall TChatForm::ClientSocketDisconnect(TObject *Sender, TCustomWinSocket *Socket)
{
//CheckBoxListen->Checked = true; // Activar el Socket y entrar en modo de escucha
// Solo si se para el servidor cuando actua como cliente
}
//---------------------------------------------------------------------------
// Cuando la Socket falla en la conexión, utilización, o cerrar una conexión.
//---------------------------------------------------------------------------
void __fastcall TChatForm::ClientSocketError(TObject *Sender, TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
Memo2->Lines->Add("Error connecting to:" + Server);
ErrorCode = 0;
}
//---------------------------------------------------------------------------
// Se produce cuando una de las conexiones a un socket de cliente se cierra.
//---------------------------------------------------------------------------
void __fastcall TChatForm::ServerSocketClientDisconnect(TObject *Sender, TCustomWinSocket *Socket)
{
StatusBar1->Panels->Items[0]->Text = "Listening...";
}
main.h
//---------------------------------------------------------------------------
#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "ScktComp.hpp"
#include <Buttons.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
#include <Menus.hpp>
//---------------------------------------------------------------------------
class TChatForm : public TForm
{
__published: // IDE-managed Components
TStatusBar *StatusBar1;
TPanel *Panel1;
TMemo *Memo1;
TMemo *Memo2;
TServerSocket *ServerSocket;
TClientSocket *ClientSocket;
TButton *Connect;
TCheckBox *CheckBoxListen;
TButton *Disconnect;
TButton *Exit;
void __fastcall Memo1KeyDown(TObject *Sender, WORD &Key,
TShiftState Shift);
void __fastcall FormCreate(TObject *Sender);
void __fastcall ClientSocketConnect(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall ClientSocketDisconnect(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall ClientSocketRead(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall ServerSocketClientRead(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall ServerSocketAccept(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall ServerSocketClientConnect(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall ClientSocketError(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode);
void __fastcall ServerSocketClientDisconnect(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall CheckBoxListenClick(TObject *Sender);
void __fastcall ConnectClick(TObject *Sender);
void __fastcall DisconnectClick(TObject *Sender);
void __fastcall ExitClick(TObject *Sender);
private: // User declarations
public: // User declarations
bool IsServer; // Actuamos como servidor
String Server; // IP del servidor a conectarse
__fastcall TChatForm(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern TChatForm *ChatForm;
//---------------------------------------------------------------------------
#endif