Telnet en c avec interface graphique (api uniquement, sans mfc ni autres cochonneries)

Soyez le premier à donner votre avis sur cette source.

Snippet vu 9 951 fois - Téléchargée 33 fois

Contenu du snippet

Bon, 2e tentative...

Je disais donc que cette source fait suite à mon ancien telnet console... Celui-ci dispose d'une GUI et permet d'envoyer des requêtes HTTP en une seule fois (ne pas oublier d'appuyer sur entrée après chaque ligne dans le memo d'envoi, le prog ne rajoute pas les CRLF...)

Source / Exemple :


#include <windows.h>
#include <winsock2.h>

#define WND_CLASS "GWIN32_TELNET"

#define IDB_CONNECT 1
#define IDB_DISCONNECT 2
#define IDB_SEND 3

#define IDE_HOST 1
#define IDE_PORT 2
#define IDE_COMMAND 3

HINSTANCE hMain = NULL;
HFONT hFont = NULL;

HWND wndMain = NULL;
HWND stcHost = NULL;
HWND edtHost = NULL;
HWND stcPort = NULL;
HWND edtPort = NULL;
HWND btnConnect = NULL;
HWND btnDisconnect = NULL;
HWND stcTransfer = NULL;
HWND edtTransfer = NULL;
HWND stcCommand = NULL;
HWND edtCommand = NULL;
HWND btnSend = NULL;

WSADATA WSAData;
char* host = NULL;
char* port = NULL;
BOOL bWinsock = FALSE;
CRITICAL_SECTION lock;
SOCKADDR_IN ClientSock;
SOCKET Client = INVALID_SOCKET;
HOSTENT* ServerInfos = NULL;
HANDLE RecvThread = NULL;
DWORD RecvThreadID = 0;
DWORD RecvThreadExitCode = 0;

void AddLine(char* c, BOOL r) {
  int n = 0;
  EnterCriticalSection(&lock);
  n = SendMessage(edtTransfer, WM_GETTEXTLENGTH, 0, 0) + 1;
  SendMessage(edtTransfer, EM_SETSEL, n, n);
  SendMessage(edtTransfer, EM_REPLACESEL, TRUE, (LPARAM) c);
  if (r) SendMessage(edtTransfer, EM_REPLACESEL, TRUE, (LPARAM) "\r\n");
  LeaveCriticalSection(&lock);
  UpdateWindow(wndMain);
}

void ResetControls(BOOL FromThread) {
  EnableWindow(edtTransfer, TRUE);
  if (RecvThread) {
    GetExitCodeThread(RecvThread, &RecvThreadExitCode);
    if (RecvThreadExitCode == STILL_ACTIVE && !FromThread) TerminateThread(RecvThread, 0);
    CloseHandle(RecvThread);
    RecvThread = NULL;
    closesocket(Client);
    Client = INVALID_SOCKET;
    SetFocus(edtTransfer);
  }
  if (host) {
    free(host);
    host = NULL;
  }
  if (port) {
    free(port);
    port = NULL;
  }
  EnableWindow(stcHost, bWinsock);
  EnableWindow(edtHost, bWinsock);
  EnableWindow(stcPort, bWinsock);
  EnableWindow(edtPort, bWinsock);
  EnableWindow(btnConnect, bWinsock);
  EnableWindow(btnDisconnect, FALSE);
  EnableWindow(stcTransfer, FALSE);
  EnableWindow(stcCommand, FALSE);
  EnableWindow(edtCommand, FALSE);
  EnableWindow(btnSend, FALSE);
  UpdateWindow(wndMain);
}

DWORD WINAPI ClientRecv(void* arg) {
  int n = 0;
  char c = 0;
  char* line = NULL;
  while (recv(Client, &c, 1, 0) > 0) {
    line = (char*) realloc(line, n + 1);
    line[n++] = c;
    if (c != '\n') continue;
    line = (char*) realloc(line, n + 1);
    line[n++] = 0;
    AddLine(line, FALSE);
    free(line);
    line = NULL;
    n = 0;
  }
  AddLine("\r\n\r\nDéconnecté du serveur.", TRUE);
  ResetControls(TRUE);
  return 0;
}

LRESULT CALLBACK wndMainProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  int n = 0;
  char* line = NULL;
  switch (uMsg) {
  case WM_ACTIVATE:
    if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) SetFocus(edtCommand);
    return 0;
  case WM_COMMAND:
    switch (HIWORD(wParam)) {
    case EN_CHANGE:
      switch (LOWORD(wParam)) {
      case IDE_HOST:
        EnableWindow(btnConnect, bWinsock && SendMessage(edtHost, WM_GETTEXTLENGTH, 0, 0) > 0 && SendMessage(edtPort, WM_GETTEXTLENGTH, 0, 0) > 0);
        break;
      case IDE_PORT:
        EnableWindow(btnConnect, bWinsock && SendMessage(edtHost, WM_GETTEXTLENGTH, 0, 0) > 0 && SendMessage(edtPort, WM_GETTEXTLENGTH, 0, 0) > 0);
        break;
      case IDE_COMMAND:
        EnableWindow(btnSend, SendMessage(edtCommand, WM_GETTEXTLENGTH, 0, 0) > 0);
        break;
      }
      break;
    case BN_CLICKED:
      switch (LOWORD(wParam)) {
      case IDB_CONNECT:
        EnableWindow(stcHost, FALSE);
        EnableWindow(edtHost, FALSE);
        EnableWindow(stcPort, FALSE);
        EnableWindow(edtPort, FALSE);
        EnableWindow(btnConnect, FALSE);
        n = SendMessage(edtHost, WM_GETTEXTLENGTH, 0, 0) + 1;
        host = (char*) malloc(n);
        SendMessage(edtHost, WM_GETTEXT, n, (LPARAM) host);
        n = SendMessage(edtPort, WM_GETTEXTLENGTH, 0, 0) + 1;
        port = (char*) malloc(n);
        SendMessage(edtPort, WM_GETTEXT, n, (LPARAM) port);
        SendMessage(edtTransfer, WM_SETTEXT, 0, (LPARAM) "");
        AddLine("Recherche du serveur... ", FALSE);
        ServerInfos = gethostbyname(host);
        if (!ServerInfos) {
          AddLine("erreur", TRUE);
          ResetControls(FALSE);
          break;
        }
        AddLine("ok", TRUE);
        memset(&ClientSock, 0, sizeof(SOCKADDR_IN));
        memcpy(&ClientSock.sin_addr.s_addr, ServerInfos->h_addr, ServerInfos->h_length);
        ClientSock.sin_port = htons(atoi(port));
        ClientSock.sin_family = AF_INET;
        Client = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        AddLine("Connexion au serveur... ", FALSE);
        if (connect(Client, (SOCKADDR*) &ClientSock, sizeof(SOCKADDR_IN))) {
          AddLine("erreur", TRUE);
          ResetControls(FALSE);
          break;
        }
        SendMessage(edtTransfer, WM_SETTEXT, 0, (LPARAM) "");
        EnableWindow(btnDisconnect, TRUE);
        EnableWindow(stcTransfer, TRUE);
        EnableWindow(edtTransfer, TRUE);
        EnableWindow(stcCommand, TRUE);
        EnableWindow(edtCommand, TRUE);
        EnableWindow(btnSend, TRUE);
        SetFocus(edtCommand);
        UpdateWindow(wndMain);
        RecvThread = CreateThread(NULL, 0, &ClientRecv, &Client, 0, &RecvThreadID);
        break;
      case IDB_DISCONNECT:
        ResetControls(FALSE);
        break;
      case IDB_SEND:
        SetFocus(edtCommand);
        n = SendMessage(edtCommand, WM_GETTEXTLENGTH, 0, 0) + 1;
        line = (char*) malloc(n);
        SendMessage(edtCommand, WM_GETTEXT, n, (LPARAM) line);
        SendMessage(edtCommand, WM_SETTEXT, 0, (LPARAM) "");
        AddLine("=> ", FALSE);
        AddLine(line, FALSE);
        send(Client, line, n - 1, 0);
        free(line);
        UpdateWindow(wndMain);
        break;
      }
      break;
    }
    return 0;
  case WM_CLOSE:
    PostQuitMessage(0);
    return 0;
  default:
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
  }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  MSG msg;
  WNDCLASSEX wc;
  hMain = hInstance;
  wc.cbSize = sizeof(WNDCLASSEX);
  wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = wndMainProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hMain;
  wc.hIcon = LoadIcon(hMain, "MAINICON");
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
  wc.lpszMenuName = NULL;
  wc.lpszClassName = WND_CLASS;
  wc.hIconSm = NULL;
  RegisterClassEx(&wc);
  InitializeCriticalSection(&lock);
  hFont = CreateFont(8, 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "MS Sans Serif");
  wndMain = CreateWindowEx(0, WND_CLASS, "Telnet Win32", WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 460, 540, HWND_DESKTOP, NULL, hMain, NULL);
  SendMessage(wndMain, WM_SETFONT, (WPARAM) hFont, TRUE);
  stcHost = CreateWindowEx(0, "STATIC", "Hôte :", WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP, 10, 10, 30, 14, wndMain, NULL, hMain, NULL);
  SendMessage(stcHost, WM_SETFONT, (WPARAM) hFont, TRUE);
  edtHost = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "EDIT", "127.0.0.1", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_LOWERCASE, 46, 6, 300, 21, wndMain, (HMENU) IDE_HOST, hMain, NULL);
  SendMessage(edtHost, WM_SETFONT, (WPARAM) hFont, TRUE);
  stcPort = CreateWindowEx(0, "STATIC", "Port :", WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP, 10, 35, 30, 14, wndMain, NULL, hMain, NULL);
  SendMessage(stcPort, WM_SETFONT, (WPARAM) hFont, TRUE);
  edtPort = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "EDIT", "23", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_LOWERCASE, 46, 31, 300, 21, wndMain, (HMENU) IDE_PORT, hMain, NULL);
  SendMessage(edtPort, WM_SETFONT, (WPARAM) hFont, TRUE);
  btnConnect = CreateWindowEx(0, "BUTTON", "Connexion", WS_CHILD | WS_VISIBLE | BS_TEXT | BS_CENTER | BS_VCENTER | BS_PUSHBUTTON | BS_NOTIFY, 360, 6, 80, 21, wndMain, (HMENU) IDB_CONNECT, hMain, NULL);
  SendMessage(btnConnect, WM_SETFONT, (WPARAM) hFont, TRUE);
  btnDisconnect = CreateWindowEx(0, "BUTTON", "Déconnexion", WS_CHILD | WS_VISIBLE | BS_TEXT | BS_CENTER | BS_VCENTER | BS_PUSHBUTTON | BS_NOTIFY, 360, 31, 80, 21, wndMain, (HMENU) IDB_DISCONNECT, hMain, NULL);
  SendMessage(btnDisconnect, WM_SETFONT, (WPARAM) hFont, TRUE);
  stcTransfer = CreateWindowEx(0, "STATIC", "Transferts :", WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP, 10, 60, 60, 14, wndMain, NULL, hMain, NULL);
  SendMessage(stcTransfer, WM_SETFONT, (WPARAM) hFont, TRUE);
  edtTransfer = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_READONLY | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 10, 75, 431, 300, wndMain, NULL, hMain, NULL);
  SendMessage(edtTransfer, WM_SETFONT, (WPARAM) hFont, TRUE);
  stcCommand = CreateWindowEx(0, "STATIC", "Requête :", WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP, 10, 380, 60, 14, wndMain, NULL, hMain, NULL);
  SendMessage(stcCommand, WM_SETFONT, (WPARAM) hFont, TRUE);
  edtCommand = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 10, 398, 431, 104, wndMain, (HMENU) IDE_COMMAND, hMain, NULL);
  SendMessage(edtCommand, WM_SETFONT, (WPARAM) hFont, TRUE);
  btnSend = CreateWindowEx(0, "BUTTON", "Envoyer", WS_CHILD | WS_VISIBLE | BS_TEXT | BS_CENTER | BS_VCENTER | BS_PUSHBUTTON | BS_NOTIFY, 360, 376, 80, 21, wndMain, (HMENU) IDB_SEND, hMain, NULL);
  SendMessage(btnSend, WM_SETFONT, (WPARAM) hFont, TRUE);
  AddLine("Initialisation de winsock... ", FALSE);
  bWinsock = !WSAStartup(MAKEWORD(2, 2), &WSAData);
  if (bWinsock) AddLine("ok", TRUE);
  else AddLine("erreur", TRUE);
  ResetControls(FALSE);
  ShowWindow(wndMain, SW_SHOW);
  while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  ResetControls(FALSE);
  DestroyWindow(wndMain);
  DeleteCriticalSection(&lock);
  DeleteObject(hFont);
  WSACleanup();
  return msg.wParam;
}

Conclusion :


Si y'a des maladresses, hésitez pas à les pointer du doigt, c'est ma toute première application graphique ;)

MAJ : placement du focus sur edtCommand... çà peut sembler inutile mais lorsqu'on utilise le prog quotidiennement, c'est appréciable ;)

PS: désolé pour le manque de commentaires...

A voir également

Ajouter un commentaire Commentaires
Messages postés
45
Date d'inscription
samedi 18 novembre 2000
Statut
Membre
Dernière intervention
10 janvier 2009

Merci pour cette source magnifique et instructive.
Des que je peu voter je met 10/10 °o°
Messages postés
787
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
7 juin 2007
1
meech> merci, çà fait plaisir :-)

Pour CreateFont : -lgdi32, en effet

kalden_mibs> euh, essaie avec une version plus récente de devcpp, ou inclus winsock2.h avant windows.h :-/
Messages postés
2
Date d'inscription
samedi 17 avril 2004
Statut
Membre
Dernière intervention
21 avril 2004

Bon alors j'ai telechargé dev-c++ je compile et j'ai droit à :

In file included from c:\docume~1\kalden\mesdoc~1\telnet.cpp:3:
C:\DEV-C_~1\Include\winsock2.h:46: unbalanced `#endif'
Messages postés
209
Date d'inscription
vendredi 11 avril 2003
Statut
Membre
Dernière intervention
14 août 2007

Idée vite fait : Essaie de le lier avec la librairie statistique libgdi32.a ou un truc du genre...
Messages postés
209
Date d'inscription
vendredi 11 avril 2003
Statut
Membre
Dernière intervention
14 août 2007

J'utilise également Dev-C++ (cet outil est terrible), et je n'ai absolument aucun problème lorsque je compile le projet, que ce soit en le liant avec la librairie statique libws2_32.a ou bien dynamiquement avec la librairie partagée de windows ws2_32.dll.

Vérifie, lors de la compilation, que les chemins des includes et des librairies sont spécifiés correctement (option -I et -L).

Peux-tu retourner l'erreur précise résultante de ton compilateur ? Au cas où nous pourrions t'aider...

NB. J'ai même pu le compiler avec GCC sous Cygwin !! (je suis fan de Cygwin ;-) En tout cas, c'est une bien belle application, même si elle demeure simple, dont nous a gratifié Nébula. Félicitations une fois de plus.
Afficher les 13 commentaires

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.