Cet utilitaire très simple permet une connexion TCP à un serveur distant.
- il permet une sauvegarde dans le fichier "historique.txt" de le connexion. (utilisation de "CreateFile", "WriteFile","CloseHandle")
- gestion avec thread (utilisation de "CreateThread")
- coloration d"un listview avec gestion de colonne (même qi une seul colonne ^^)
- implémentation des socket (création + envoie/réception...)
petite fonctions pratiques:
- utilisation d'une DialogBox comme fenêtre principale
- application d'une icone à la fenêtre principal
- activer /désactiver un item...
Ce code est assez simple, j'espère que les débutants y trouveront leur bonheur :)
Source / Exemple :
//------------------------------------------------------------------------------
// Projet TestServ : Utilitaire de type Telnet avec enregistrement
// d'historique + coloration +sauvegarde des commandes
// Auteur : Hanteville Nicolas
// Fichier : main.c
// Version : 0.1
// Date de modification : 30/06/2007
// Description : programme principale + fonction / procédures
// Environnement : compatiblité DEVCPP / VISUAL C++ / BORLAND C++ 5.x
//------------------------------------------------------------------------------
#include "ressources.h"
//------------------------------------------------------------------------------
// ajout de l'item avec le texte en paramètre
//Type: FALSE = Envoie / TRUE = Réception
void AjouterItem(char *texte,BOOL Type)
{
char tmp[TAILLE_REQUETE];
char *t = texte;
LVITEM lvi;//une ligne
char car[2];
if (!Type)
{
strcpy(tmp,"Envoyé:");
strncat(tmp,texte,TAILLE_REQUETE);
strncat(tmp,"\0",TAILLE_REQUETE);
}else
{
strcpy(tmp,"Recue:");
while(*t++)
{
if (*t == '\r')
strncat(tmp,"<CR>",TAILLE_REQUETE);
else if (*t == '\n')
strncat(tmp,"<LF>",TAILLE_REQUETE);
else
{
car[0] = *t;
car[1] = 0;
strncat(tmp,car,TAILLE_REQUETE);
}
}
}
//ajout d'un item
lvi.mask = LVIF_TEXT|LVIF_PARAM;
lvi.iSubItem = 0;
lvi.lParam = 0;
lvi.pszText=tmp;
lvi.iItem = 0;
car[0] = ListView_InsertItem(H_LISTVIEW, &lvi);
if (log)//ajouter item au fichier de log
{
strncat(tmp,"\r\n",TAILLE_REQUETE);
WriteFile(HLog,tmp,strlen(tmp),&copiee,0);
}
ListView_RedrawItems(H_LISTVIEW,car[0],car[0]);
}
//------------------------------------------------------------------------------
// init de la connexion + traitement début de fichier
BOOL MyConnect()
{
//init du réseau
WSADATA wsaData;//variable pour initialisé la connexion
SOCKADDR_IN sinfo; // la configuration du socket
struct in_addr **a;
char tmp[TAILLE_REQUETE];
char serveur[TAILLE_REQUETE]="";
char port[TAILLE_PORT]="";
char *pt;
BOOL ETAT_IP = TRUE;
if (log)
{
//ouverture du fichier de log
HLog = CreateFile("Historique.txt",GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_FLAG_SEQUENTIAL_SCAN,0);
if (HLog == INVALID_HANDLE_VALUE)
{
CloseHandle(HLog);
return FALSE;
}
//on se place a la fin du fichier
SetFilePointer(HLog,GetFileSize(HLog,NULL),0,FILE_BEGIN);
}
if (!WSAStartup(0x0202,&wsaData))// si pas d'erreur
{
//init du socket
sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sinfo.sin_family = AF_INET;
//récupération du port
GetWindowText(H_PORT,port,TAILLE_PORT);
if (!port)
{
shutdown(sock,2);
WSACleanup();
MessageBox(0,"Port non valide!","Erreur!!!",MB_OK|MB_TOPMOST|MB_ICONWARNING);
return FALSE;
}
sinfo.sin_port = htons(atoi(port));
//récupération de l'adresse du serveur
GetWindowText(H_SERVEUR,serveur,TAILLE_REQUETE);
if (!serveur)
{
shutdown(sock,2);
WSACleanup();
MessageBox(0,"Adresse du serveur non valide","Erreur!!!",MB_OK|MB_TOPMOST|MB_ICONWARNING);
return FALSE;
}
//test si c'est une adresse ip ou autre
pt = serveur;
while(*pt && ETAT_IP)
{
if ((*pt <48 && *pt != 46) || (*pt >57 && *pt != 46)) //si pas un chiffre et pas un point alors pas une ip
ETAT_IP = FALSE;
pt++;
}
if (!ETAT_IP) //résolution du nom
{
struct hostent *host;
if (host=gethostbyname(serveur))
{
a = (struct in_addr **)host->h_addr_list;
sinfo.sin_addr.s_addr=inet_addr(inet_ntoa(**a));
}else
{
shutdown(sock,2);
WSACleanup();
MessageBox(0,"Résolution de l'adresse du serveur impossible","Erreur!!!",MB_OK|MB_TOPMOST|MB_ICONWARNING);
return FALSE;
}
}else
sinfo.sin_addr.s_addr=inet_addr(serveur);
//connexion
if (connect(sock,(SOCKADDR *)&sinfo,sizeof(sinfo))!=0)
{
closesocket(sock);
shutdown(sock,2);
WSACleanup();
MessageBox(0,"Connexion au serveur impossible","Erreur!!!",MB_OK|MB_TOPMOST|MB_ICONWARNING);
return FALSE;
}
//ajout sur le liste view de la trame de connexion
if (!ETAT_IP)
snprintf(tmp,TAILLE_REQUETE,"[]Connexion au serveur : \"%s\" (%s) port:%s Réussi!!!",serveur,inet_ntoa(**a),port);
else
snprintf(tmp,TAILLE_REQUETE,"[]Connexion au serveur : \"%s\" port:%s Réussi!!!",serveur,port);
AjouterItem(tmp,FALSE);
//lancement du thread de récupération
//MyThread = (HWND)CreateThread(NULL, 0,ThreadRec,0,0,&IDThread);
if (CreateThread(NULL, 0,ThreadRec,0,0,0) ==0)
{
closesocket(sock);
shutdown(sock,2);
WSACleanup();
MessageBox(0,"Réception des trames impossible","Erreur!!!",MB_OK|MB_TOPMOST|MB_ICONWARNING);
return FALSE;
}
return TRUE;
}else
return FALSE;
}
//------------------------------------------------------------------------------
// fonction de fin de connexion
DWORD WINAPI MyDisConnect(LPVOID lParam)
{
CONNECTEE = FALSE;
//désactive le bouton envoyer
EnableWindow(H_BUTTON_ENVOYER, FALSE);
//déconnexion
closesocket(sock);
shutdown(sock,2);
WSACleanup();
if (log)
{
WriteFile(HLog,"--------------------\n\n",22,&copiee,0);
CloseHandle(HLog);
}
}
//------------------------------------------------------------------------------
// fonction d'envoie de trames
DWORD WINAPI EnvoieTrame(LPVOID lParam)
{
char requete[TAILLE_REQUETE];
//récupération de la zone de texte
GetWindowText(H_COMMANDE,requete,TAILLE_REQUETE);
//ajout de la requète a la chaine ^^
if (requete[0] != 0)
SendMessage(H_COMMANDE, CB_ADDSTRING,0, (LPARAM)requete);
//poste traitement pour gestion d'affichage
strncat(requete,"\r\n",TAILLE_REQUETE); //retour a la ligne
//envoie
send(sock,requete,strlen(requete),0);
//ajout de la trame a la liste view
requete[strlen(requete)-2]=0;
strncat(requete,"<CR><LF>\0",TAILLE_REQUETE);
AjouterItem(requete,FALSE);
//vidage de la zone mémoire
SetWindowText(H_COMMANDE,"");
}
//------------------------------------------------------------------------------
// fonction de réception des trames
DWORD WINAPI ThreadRec(LPVOID lParam)
{
char requete[TAILLE_REQUETE];
//récupération en non bloquant
int retour=1;
//on quitte quand la connexion est terminé
//+le socket est fermé
//+ erreur de réception ou fin de connexion
while(CONNECTEE && retour > 0)
{
//récupération de la trame
retour = recv(sock,requete,TAILLE_REQUETE,0);
//affichage de la trame dans la liste view
if (retour > 0)
{
requete[retour]=0; // gestion \r\n
AjouterItem(requete,TRUE);
}
}
if (CONNECTEE)
{
//désactive le bouton envoyer
EnableWindow(H_BUTTON_ENVOYER, FALSE);
//déconnexion
CONNECTEE = FALSE;
closesocket(sock);
shutdown(sock,2);
WSACleanup();
}
AjouterItem("[]Déconnecté du serveur!!!",FALSE);
SetWindowText(H_BUTTON_CONNECTE,TXT_CONNECTE);
//active les paramètres
EnableWindow(H_PORT, TRUE);
EnableWindow(H_SERVEUR, TRUE);
EnableWindow(H_BUTTON_LOG, TRUE);
}
//------------------------------------------------------------------------------
//gestion des appels et msg sur le fenêtre principale
HRESULT DlgProc(HWND hwnd,UINT Msg,WPARAM Wparam,LPARAM lParam)
{
LPDRAWITEMSTRUCT lpDrawItem;
RECT rect;
char tmp [TAILLE_REQUETE];
switch(Msg)
{
case WM_DRAWITEM://permet la coloration des lignes
//traitement par ligne
lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
if(ListView_GetItemState(H_LISTVIEW, lpDrawItem->itemID, LVIS_SELECTED) & LVIS_SELECTED)
// L'élément est séléctionné
FillRect(lpDrawItem->hDC, &lpDrawItem->rcItem, (HBRUSH)GetStockObject(GRAY_BRUSH));
else //fond des lignes
FillRect(lpDrawItem->hDC, &lpDrawItem->rcItem, GetSysColorBrush(COLOR_WINDOW));
//récupération du texte de la ligne + zone de l'item
ListView_GetItemText(H_LISTVIEW,lpDrawItem->itemID,0,tmp,TAILLE_REQUETE);
ListView_GetItemRect(H_LISTVIEW, lpDrawItem->itemID, &rect, LVIR_BOUNDS);
//si commence par
if (tmp[0] == 'R')//réception en rouge
{
SetTextColor(lpDrawItem->hDC,RGB(255, 0, 0));
}
else//sinon en bleu
{
SetTextColor(lpDrawItem->hDC,RGB(0, 0, 255));
}
//écriture du texte + zone d'écriture
rect.left+=2;
rect.right= rect.left + ListView_GetColumnWidth(H_LISTVIEW, 0)-4;
DrawText(lpDrawItem->hDC,tmp, strlen(tmp), &rect, DT_VCENTER);
break;
case WM_INITDIALOG:
InitCommonControls();
CONNECTEE = FALSE;
log = FALSE;
H_LISTVIEW=GetDlgItem(hwnd,LST_INFO);
H_BUTTON_ENVOYER=GetDlgItem(hwnd,BT_ENVOYER);
H_PORT = GetDlgItem(hwnd,PORT);
H_SERVEUR = GetDlgItem(hwnd,SERVEUR);
H_BUTTON_CONNECTE = GetDlgItem(hwnd,BT_CONNECT);
H_COMMANDE = GetDlgItem(hwnd,COMMANDE);
H_BUTTON_LOG = GetDlgItem(hwnd,BT_LOG);
EnableWindow(H_BUTTON_ENVOYER, FALSE);
//icone sur notre fenêtre
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(Hinst, MAKEINTRESOURCE(ID_ICON)));
LVCOLUMN lvc; //gestion colonne de la listeview
SendMessage(H_LISTVIEW,LVM_FIRST + 31,(WPARAM )0,(LPARAM )0);
lvc.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_FMT;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = 600; //taille colonne
lvc.pszText = "-- Commandes --"; //texte de la colonne
ListView_InsertColumn(H_LISTVIEW, 0, &lvc); //ajout colonne
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_NOTIFY://gestion du double click sur un item
if ((LOWORD(Wparam) == LST_INFO) && (((LPNMHDR)lParam)->code == NM_DBLCLK))
{
char tmp[TAILLE_REQUETE];
//comptenu de la sélection
ListView_GetItemText(H_LISTVIEW,(unsigned int)SendMessage(H_LISTVIEW,LVM_GETNEXTITEM,(WPARAM)-1,LVNI_FOCUSED),0,tmp,TAILLE_REQUETE);
//on affiche
MessageBox(0,tmp,"Information Trame",MB_OK|MB_TOPMOST);
}
break;
case WM_COMMAND :
switch(LOWORD(Wparam))
{
case BT_ENVOYER:
CreateThread(NULL,0,EnvoieTrame,0,0,0);
break;
case BT_CONNECT:
if (CONNECTEE)
{
CreateThread(NULL,0,MyDisConnect,0,0,0);
}else
{
if (MyConnect())
{
CONNECTEE = TRUE;
SetWindowText(H_BUTTON_CONNECTE,TXT_DECONNECTE);
//active le bouton envoyer
EnableWindow(H_BUTTON_ENVOYER, TRUE);
//désactive les paramètres
EnableWindow(H_PORT, FALSE);
EnableWindow(H_SERVEUR, FALSE);
EnableWindow(H_BUTTON_LOG, FALSE);
}
}
break;
case BT_LOG://maj de la gestion des logs
if (!log) log=TRUE;
else log=FALSE;
break;
}
break;
}
return 0;
}
//------------------------------------------------------------------------------
//fonction principal (main)
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hinstancePRECEDENTE, LPSTR CmdLine, int CmdShow)
{
Hinst = hInst;
//création de la fenêtre
DialogBox(0,MAKEINTRESOURCE(TestServeur),GetDesktopWindow(),(DLGPROC)DlgProc);
return 0;
}
Conclusion :
N'hésitez pas à poser des questions :)
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.