Ce programme créé sous C++Builder 6 est une démo mettant en oeuvre les sockets VCL, c'est-à-dire TServerSocket et TClientSocket. Il permet d'envoyer des messages entre 2 machines tournant sous Windows, en les configurant soit en Client, soit en Server, soit les deux.
Le programme a été documenté avec Doxygen.
Un User's Manual est fourni au format PDF.
Source / Exemple :
/**
- \file Unit1.cpp
- \brief Application de test des sockets sous C++Builder 6
- \author JEHANNO didier
- \author Laboratoire de l'Accélérateur Linéaire (\b LAL)
- \author Unité Mixte IN2P3 - Université Paris-Sud
- \author UMR 8607 - Physique Nucléaire et Corpusculaire (PNC)
- \author Campus Universitaire d'Orsay - Bâtiment 200
- \author 91898 ORSAY cedex
- \date 17.12.2004
- \version 1.0 création
- \version 1.1 Appel de P. Plasson du LESIA (utilisation Connections[])
*
- \note Ce programme teste les sockets sous C++ Builder 6, version pro.
- \note L'utilisateur peut se connecter :
- \note \li soit comme \b SERVER à un client distant en utilisant \c TServerSocket
- \note \li soit comme \b CLIENT à un \b SERVER distant en utilisant \c TClientSocket
- \note \li soit comme \b CLIENT/SERVER connecté à un \b SERVER/CLIENT distant
- \note \li soit comme \b CLIENT/SERVER connecté à lui-même
- \note Tous les ports semblent fonctionner.
*
- \warning Le programme EST TRES DEFAILLANT sur les modes dégradés car les tests en
- \warning cas d'erreurs sont quasi inexistants (exemple à ne pas suivre).
*
- \remarks Ce programme est compatible \b DOXYGEN (www.doxygen.org) pour la documentation.
- \remarks Un User's Manual est fourni au format \b PDF.
- /
/** @defgroup BUILDER Fonctions associées à la gestion des fenêtres */
/** @defgroup SERVER Fonctions associées à la partie SERVER */
/** @defgroup CLIENT Fonctions associées à la partie CLIENT */
/** @defgroup DISPLAY Fonction associée à la partie Affichage */
#include <vcl.h>
#pragma hdrstop
#include "SocketFP.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
/** Formulaire de l'application */
TForm1 *Form1;
/**
- @ingroup BUILDER
- \brief C++Builder
- /
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
/**#######################################################################
- TRAITEMENT DES EVENEMENTS FENETRE
- #########################################################################*/
/**
- @ingroup BUILDER
- \brief L'événement traité ici est la \b création de la fenêtre principale.
- \brief On souhaite afficher le \b nom de la machine locale et son adresse \b IP.
- /
void __fastcall TForm1::FormCreate(TObject *Sender)
{
/** chaine de caracteres recevant le nom de la machine locale */
char NameLocalMachine[255];
/** struct PHOSTENT correspondant à la valeur retournée par \c gethostbyname */
PHOSTENT InfosLocalMachine;
/** AnsiString recevant la valeur de retour de \c inet_ntoa */
AnsiString AdressIPLocalMachine;
/** Fermer la connexion du Socket CLIENT */
ClientSocket->Active = false;
/** Fermer la connexion du Socket SERVER */
ServerSocket->Active = false;
/** Recherche de l'adresse de la machine */
if( gethostname (NameLocalMachine, sizeof(NameLocalMachine)) == 0)
{
/** nom de la machine locale */
EditLocalName->Text = (AnsiString)NameLocalMachine;
/** SI la valeur retournée est OK ALORS */
if((InfosLocalMachine = gethostbyname(NameLocalMachine)) != NULL)
{
/** Recherche de l'adresse \b IP */
AdressIPLocalMachine = inet_ntoa(*(in_addr *)*InfosLocalMachine->h_addr_list);
/** Affichage adresse \b IP */
EditLocalAddress->Text = AdressIPLocalMachine;
/** FINSI */
}
/** FINSI */
}
}
/**
- @ingroup BUILDER
- \brief L'événement traité ici est la fermeture de la fenêtre principale
- /
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
/** Fermer la connexion du Socket \b CLIENT */
ClientSocket->Active = false;
/** Fermer la connexion du Socket \b SERVER */
ServerSocket->Active = false;
}
/**#######################################################################
- TRAITEMENT DE LA SOCKET CLIENT : ClientSocket
- #########################################################################*/
/**
- @ingroup CLIENT
- \brief L'événement traité ici est un click sur le BOUTON \c ButtonConnectToDistServer.
- \brief L'utilisateur veut :
- \brief \li soit se connecter au \b SERVER distant via la socket locale \b CLIENT
- \brief \li soit se déconnecter
- /
void __fastcall TForm1::ButtonConnectToDistServerClick(TObject *Sender)
{
/** SI on n'est pas connecté au SERVER distant ALORS */
if (ClientSocket->Active == false)
{
/** Renseigner le N° de port du serveur */
ClientSocket->Port = EditDistServerPort->Text.ToInt();
/** Renseigner l'adresse du \b HOST = \b SERVER avec la valeur saisie */
ClientSocket->Host = EditDistServerAddress->Text;
/** Lancer la connexion de la Socket \b CLIENT */
ClientSocket->Active = true;
/** Changer l'intitulé du bouton*/
ButtonConnectToDistServer->Caption = (AnsiString)"DISCONNECT from Dist. SERVER";
}
/** SINON : déjà connecté */
else
{
/** Déconnecter la Socket \b CLIENT */
ClientSocket->Active = false;
/** Changer l'intitulé du bouton */
ButtonConnectToDistServer->Caption = (AnsiString)"CONNECT to Dist. SERVER";
/** Désactiver la CHECKBOX dédiée */
CheckBoxConnectedToDistServer->Checked = false;
/** Effacer les anciens messages */
EditMessageToDistServer->Clear();
EditMessageFromDistServer->Clear();
}
}
/**
- @ingroup CLIENT
- \brief L'événement traité ici est une CONNEXION côté SERVER distant.
- \brief On coche la case dédiée.
- /
void __fastcall TForm1::ClientSocketConnect(TObject *Sender,
TCustomWinSocket *Socket)
{
/** Valider la CHECHBOX dédiée */
CheckBoxConnectedToDistServer->Checked = true;
}
/**
- @ingroup CLIENT
- \brief L'événement traité ici est une \b DECONNEXION de la socket \b CLIENT
- \brief \li soit sur demande de l'utilisateur (\c ButtonConnectToDistServer)
- \brief \li soit à cause d'une déconnexion matérielle
- /
void __fastcall TForm1::ClientSocketDisconnect(TObject *Sender,
TCustomWinSocket *Socket)
{
/** Dévalider la CHECHBOX dédiée */
CheckBoxConnectedToDistServer->Checked = false;
/** Effacer les anciens messages */
EditMessageToDistServer->Clear();
EditMessageFromDistServer->Clear();
}
/**
- @ingroup CLIENT
- \brief Le PC Local est \b CLIENT et l'utilisateur a cliqué sur \c ButtonSendToDistServer
- \brief pour demander l'envoi de la chaine \c EditMessageToDistServer au PC distant \b SERVER
- /
void __fastcall TForm1::ButtonSendToDistServerClick(TObject *Sender)
{
/** SI on est connecté au server ALORS */
if (ClientSocket->Active == true)
{
/** Transmettre le message EditMessageToDistServer au \b SERVER distant */
ClientSocket->Socket->SendText(EditMessageToDistServer->Text);
}
}
/**
- @ingroup CLIENT
- \brief L'événement traité ici est une \b RECEPTION de message \b VENANT du \b SERVER distant
- \brief qui est transmis au \b PC LOCAL sur sa socket \b CLIENT.
- \brief L'événement utilisé est : \c OnRead, c'est donc un \b READ vu côté \b CLIENT
- \brief (le CLIENT local lit un message SERVER distant)
- /
void __fastcall TForm1::ClientSocketRead(TObject *Sender,
TCustomWinSocket *Socket)
{
/** Afficher le message VENANT du SERVER distant dans \c EditMessageFromDistServer */
EditMessageFromDistServer->Text = ClientSocket->Socket->ReceiveText();
}
/**#######################################################################
- TRAITEMENT DE LA SOCKET SERVER : ServerSocket
- #########################################################################*/
/**
- @ingroup SERVER
- \brief L'événement traité ici est un click sur le BOUTON \c ButtonActivateLocServer.
- \brief L'utilisateur veut :
- \brief \li soit \b ACTIVER le PC LOCAL en tant que SERVER.
- \brief \li soit le \b DESACTIVER
- /
void __fastcall TForm1::ButtonActivateLocServerClick(TObject *Sender)
{
/** SI le server n'est pas activé ALORS */
if (ServerSocket->Active == false)
{
/** Le port est déterminé par l'utilisateur dans \c EditLocServerPort */
ServerSocket->Port = EditLocServerPort->Text.ToInt();
/** Activer la socket \b SERVER */
ServerSocket->Active = true;
/** Changer l'intitulé du BOUTON \c ButtonActivateLocServer */
ButtonActivateLocServer->Caption = (AnsiString)"UNACTIVATE Loc. SERVER";
/** Activer la CHECKBOX dédiée */
CheckBoxActivatedAsLocServer->Checked = true;
}
/** SINON */
else
{
/** Désactiver la socket \b SERVER */
ServerSocket->Active = false;
/** Changer l'intitulé du BOUTON \c ButtonActivateLocServer */
ButtonActivateLocServer->Caption = (AnsiString)"ACTIVATE Loc. SERVER";
/** Désactiver la CHECKBOX dédiée */
CheckBoxActivatedAsLocServer->Checked = false;
/** Effacer les anciens messages */
EditMessageToDistClient->Clear();
EditMessageFromDistClient->Clear();
/** FINSI */
}
}
/**
- @ingroup SERVER
- \brief L'événement traité ici est une \b RECEPTION de message \b VENANT du \b CLIENT distant
- \brief qui est transmis au \b PC \b LOCAL sur sa socket \b SERVER.
- \brief L'événement utilisé est : \c OnClientRead, c'est donc un \b READ vu côté \b SERVER
- \brief (le SERVER local lit un message CLIENT distant)
- /
void __fastcall TForm1::ServerSocketClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
/** Afficher le message \b VENANT du \b CLIENT distant */
EditMessageFromDistClient->Text = Socket->ReceiveText();
}
/**
- @ingroup SERVER
- \brief L'événement traité ici est une \b ONNEXION côté \b CLIENT distant.
- \brief On coche la case dédiée et on indique au PC LOCAL quelle est l'adresse IP
- \brief du CLIENT distant qui vient de se connecter sur la socket SERVER.
- /
void __fastcall TForm1::ServerSocketClientConnect(TObject *Sender,
TCustomWinSocket *Socket)
{
/** Valider la CHECHBOX dédiée */
CheckBoxDistClientConnected->Checked = true;
/** Renseigner l'adresse du Client dans \c EditDistClientAddress */
EditDistClientAddress->Text = Socket->RemoteAddress;
}
/**
- @ingroup SERVER
- \brief L'événement traité ici est une DECONNEXION de la socket SERVER
- \brief \li soit sur demande de l'utilisateur (\c ButtonActivateLocServer)
- \brief \li soit à cause d'une déconnexion matérielle
- /
void __fastcall TForm1::ServerSocketClientDisconnect(TObject *Sender,
TCustomWinSocket *Socket)
{
/** Dévalider la CHECHBOX dédiée */
CheckBoxDistClientConnected->Checked = false;
/** Changer l'intitulé du BOUTON \c ButtonActivateLocServer */
ButtonActivateLocServer->Caption = (AnsiString)"ACTIVATE Loc. SERVER";
/** Effacer l'adresse du Client */
EditDistClientAddress->Clear();
/** Effacer les anciens messages */
EditMessageFromDistClient->Clear();
EditMessageToDistClient->Clear();
}
/**
- @ingroup SERVER
- \brief Le PC Local est \b SERVER et l'utilisateur a cliqué sur \c ButtonSendToDistClient
- \brief pour demander l'envoi de la chaine \c EditMessageToDistClient au PC distant CLIENT
- /
void __fastcall TForm1::ButtonSendToDistClientClick(TObject *Sender)
{
/** Le PC Local étant \b SERVER, plusieurs \b CLIENTS distants peuvent être
- connectés en même temps. Pour envoyer un message à un CLIENT précis,
- la propriété \c Connections de Socket donne la liste des clients connectés.
- Ici, on suppose qu'un SEUL client est connecté, donc \c Connections[0]
- a été utilisé.
- Le message à envoyer est récupéré depuis \c EditMessageToDistClient */
ServerSocket->Socket->Connections[0]->SendText(EditMessageToDistClient->Text);
}
/**#######################################################################
- AFFICHAGE (aucun rapport avec les SOCKETS)
- #########################################################################*/
/**
- @ingroup DISPLAY
- \brief Toute la gestion de l'affichage est ici. On utilise un \b TIMER CYCLIQUE
- \brief TimerDisplay cadencé à \b 20ms.
- \brief A chaque fois qu'une socket est \b ACTIVE, on fait se déplacer 2 petits
- \brief logos dans les 2 sens de transfert (socket \b full-dupplex)
- /
void __fastcall TForm1::TimerDisplayTimer(TObject *Sender)
{
/** SI la socket CLIENT n'est pas activée ALORS */
if (ClientSocket->Active == false)
{
/** Ramener aux positions d'init */
ImageBits1->Left = 315;
ImageBits2->Left = 471;
}
/** SINON */
else
{
/** Déplacer le widget du Client Local vers le Server distant */
if (ImageBits1->Left <= 446) ImageBits1->Left += 2;
else ImageBits1->Left = 315;
/** Déplacer le widget du Server distant vers le Client Local */
if (ImageBits2->Left >= 329) ImageBits2->Left -=2;
else ImageBits2->Left = 471;
/** FINSI */
}
/** SI la socket SERVER n'est pas activée ALORS */
if (ServerSocket->Active == false)
{
/** Ramener aux positions d'init */
ImageBits3->Left = 315;
ImageBits4->Left = 471;
}
/** SINON */
else
{
/** Déplacer le widget du Client Local vers le Server distant */
if (ImageBits3->Left <= 446) ImageBits3->Left += 2;
else ImageBits3->Left = 315;
/** Déplacer le widget du Server distant vers le Client Local */
if (ImageBits4->Left >= 329) ImageBits4->Left -=2;
else ImageBits4->Left = 471;
/** FINSI */
}
}
/**#######################################################################
- FIN DU PROGRAMME
- #########################################################################*/
Conclusion :
Le programme a bénéficié de certains codes donnés en exemple sur le site. L'intention était de n'écrire aucune application spécifique, just d'implémenter les sockets sous C++Builder 6.
Le programme est très largement améliorable.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.