C/C++ [C++] Connexion au serveur D2 en socket

Inscrit
15 Avril 2011
Messages
457
Reactions
1
#1
Salut, je souhaite créé un petit bot en socket, je ne sais pas encore ce qu'il va faire, pas un truc énorme ça c'est sûr, peut-être un simple bot de fauche. Mais pour l'instant, je n'en suis pas là, car je cherche à me connecter au serveur D2. Au début, je voulais le coder en C# mais je ne maîtrise vraiment pas le .NET et je préfère en rester au C++, que j'étudie en cours. Donc, j'ai réussi à créer ma socket (voir le code en dessous) mais le soucis, c'est qu'en C++, la socket retourne le paquet reçu en tableau de char, et ça donne du code ASCII incompréhensible. Voici ce que je reçois :





et voici ce que j'aimerais recevoir (socket codé en AutoIt qui lui reçoit directement en string) :



J'aimerais recevoir directement en string au format hexadécimal (je ne sais pas si c'est possible), ou recevoir en char* et convertir après en string au format hexadécimal, car le format hexadécimal est utilisé pour connaître l'id des paquets.
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#3
Ah ouais, désolé j'ai pas pensé à regarder dans la section "Demande de tutos". J'ai parfaitement compris le sniffage grâce au tuto de Maxilia que j'avais déjà lu plusieurs fois, maintenant je vais essayer de traduire en C++ le parseur de Toons que je ne connaissais pas. Je vous tiens au jus ;)
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#4
Alors, j'ai pas mal progressé, sachant que je ne connaissais rien en socket et en thread :)
Mais j'ai un problème qui persiste, je sens que je suis proche du but, c'est un problème de pointeur générique, je ne maîtrise pas donc voici mon code :

(C'est loin d'être terminé !)

Code:
#include <winsock2.h>                                                                       // bibliothèque pour utiliser les sockets
#include <iostream>
#include <string>
#include <pthread.h>
using namespace std;

void* ecoute(void* data, char buffer[1000], SOCKET sock, SOCKADDR_IN sin);
void* data;

int main()
{
    char buffer[1000];                                                                      // tableau de la mémoire tampon
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);                                                    // initialiser la bibliothèque winsock2
    SOCKET sock;                                                                            // déclarer le type socket
    SOCKADDR_IN sin;                                                                        // déclarer la structure de paramétrage de la socket
    sin.sin_addr.s_addr	= inet_addr("213.248.126.145");                                     // IP de la socket
    sin.sin_family		= AF_INET;                                                          // type de socket
    sin.sin_port		= htons(5555);                                                      // port de la socket
    sock = socket(AF_INET,SOCK_STREAM,0);                                                   // création de la socket
    bind(sock, (SOCKADDR *)&sin, sizeof(sin));                                              // association de la socket aux informations précédentes
    pthread_t thread;                                                                       // créatin du thread
    pthread_create(&thread, NULL, ecoute(data, &buffer[1000], sock, sin), NULL); ERREUR A CETTE LIGNE !!!            // exécuter la fonction en parallèle
    closesocket(sock);                                                                      // fermeture de la socket
    WSACleanup();                                                                           // libérer les ressources allouées par la fonction WSAStartup()
}

void* ecoute(void* data, char buffer[1000], SOCKET sock, SOCKADDR_IN sin)
{
    while (connect(sock, (SOCKADDR *)&sin, sizeof(sin))!= SOCKET_ERROR)
    {
        int i=recv(sock,buffer,sizeof(buffer), 0);
        cout<<"Nombre d'octets recus : "<<i<<endl;
        for (int j=0;j<i;j++)
        {
            cout<<"0x"<<buffer[j]<<" ";
        }
    }
    return NULL;
}
L'erreur est : "invalid conversion from 'void*' to 'void* (*)(void*)'", j'ai essayé de mettre des parenthèses, des '&' ou des '*' un peu partout ^^' mais ça ne marche pas, je n'ai jamais la même erreur, mais celle-ci semble être la principale. J'ai signalé la ligne d'où vient l'erreur.
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#5
J'ai résolu l'erreur en me servant du quatrième paramètre de pthread_create qui permet de passer une variable en paramètre à la fonction thread, j'ai donc créé une structure où j'y ai mis mes 3 variables, j'ai mis la structure en quatrième paramètre mais ça ne fonctionne pas :S Dans la fonction thread ("ecoute"), j'ai une erreur qui me dit que 'p' (ma structure) n'est pas déclarée. Voici mon code :

Code:
#include <winsock2.h>                                                                       // bibliothèque pour utiliser les sockets
#include <iostream>
#include <string>
#include <pthread.h>
using namespace std;

void* ecoute(void* data);

struct parametres_socket
    {
        char buffer[1000];                                                                  // tableau de la mémoire tampon
        SOCKET sock;                                                                        // déclarer le type socket
        SOCKADDR_IN sin;                                                                    // déclarer la structure de paramétrage de la socket
    };


int main()
{
    parametres_socket p;
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);                                                    // initialiser la bibliothèque winsock2
    (p.sin).sin_addr.s_addr = inet_addr("213.248.126.145");                                        // IP de la socket
    (p.sin).sin_family = AF_INET;                                                               // type de socket
    (p.sin).sin_port = htons(5555);                                                               // port de la socket
    p.sock = socket(AF_INET,SOCK_STREAM,0);                                                   // création de la socket
    bind(p.sock, (SOCKADDR *)&p.sin, sizeof(p.sin));                                              // association de la socket aux informations précédentes
    pthread_t thread;                                                                       // création du thread
    pthread_create(&thread,NULL,ecoute,&p);                                            // exécuter la fonction en parallèle
    closesocket(p.sock);                                                                      // fermeture de la socket
    WSACleanup();                                                                           // libérer les ressources allouées par la fonction WSAStartup()
}

void* ecoute(void* data)
{
    connect(p.sock, (SOCKADDR *)&p.sin, sizeof(p.sin));
    int i=recv(p.sock,p.buffer,sizeof(p.buffer), 0);
    cout<<"Nombre d'octets recus : "<<i<<endl;
    for (int j=0;j<i;j++)
    {
        cout<<"0x"<<p.buffer[j]<<" ";
    }
    return NULL;
}
 
Inscrit
22 Octobre 2011
Messages
34
Reactions
0
#6
La variable 'p' n'est effectivement pas déclarée dans la portée de ta fonction 'ecoute'. Le principe de passer un paramètre à une fonction c'est de pouvoir le récuperer. Pour ça, il te suffit de faire au début de ta fonction ecoute:
Code:
parametres_socket* p = reinterpret_cast<parametres_socket*>(data);
D'autre part avec ton code ton programme va se couper quasi instantanément, il faut que tu join le thread que tu créés.
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#7
Merci de ton aide mais j'avais déjà résolu le problème, on m'a aidé sur SdZ, voici le code résolu :

Code:
#include <iostream>
#include <string>
#include <pthread.h>
using namespace std;

void* ecoute(void* data);                                                                       // déclaration de la fonction thread

struct parametres_socket
    {
        char buffer[1000];                                                                      // tableau de la mémoire tampon
        SOCKET sock;                                                                            // déclarer le type socket
        SOCKADDR_IN sin;                                                                        // déclarer la structure de paramétrage du socket
    };

int main()
{
    parametres_socket p;
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);                                                        // initialiser la bibliothèque winsock2
    (p.sin).sin_addr.s_addr = inet_addr("213.248.126.180");                                     // IP du socket
    (p.sin).sin_family = AF_INET;                                                               // type de socket
    (p.sin).sin_port = htons(5555);                                                             // port du socket
    p.sock = socket(AF_INET,SOCK_STREAM,0);                                                     // création du socket
    bind(p.sock, (SOCKADDR *)&p.sin, sizeof(p.sin));                                            // association du socket aux informations précédentes
    pthread_t thread;                                                                           // création du thread
    int erreur=pthread_create(&thread,NULL,ecoute,static_cast<void*>(&p));                      // exécuter la fonction en parallèle
    if (erreur!=0)                                                                              // test pour savoir si le thread est lancé ou pas
        cout<<"Erreur : socket non lancé !"<<endl;
    while(ecoute != NULL)                                                                       // on attend que le thread se termine
        Sleep(50);
    closesocket(p.sock);                                                                        // fermeture de la socket
    WSACleanup();                                                                               // libérer les ressources allouées par la fonction WSAStartup()
}

void* ecoute(void* data)                                                                        // fonction thread
{
    parametres_socket* p = static_cast<parametres_socket*>(data);                               //
    connect(p->sock, (SOCKADDR *)&p->sin, sizeof(p->sin));                                      // connexion au socket
    while (1)
    {
        int i=recv(p->sock,p->buffer,sizeof(p->buffer), 0);                                     // réception et stockage dans la variable i
        cout<<"Nombre d'octets recus : "<<i<<endl;                                              // affichage du nombre d'octets reçus
        for (int j=0;j<i;j++)
        {
            cout<<"0x"<<p->buffer[j]<<" ";
        }
        cout<<endl;
    }
    return NULL;
}
Mais je n'ai pas encore fini la traduction.
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#8
rien a voire avec le reste mais le buffer est trop petit , il faut 8192 octets et qu'il soit en unsigned char pour eviter des problemes par la suite
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#9
C'est parce que le paquet le plus lourd pèse 8192 octets qu'il faut qu'il soit de 8192 octets ?

Et je n'arrive pas à mettre le buffer en unsigned char :S
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#10
unsigned char buffer[8192]; // oui le plus gros paquet fera 8192 octets
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#11
J'ai déjà essayé ça quand même^^
La fonction recv() provoque une erreur car elle veut un tableau de char, pas un tableau d'unsigned char. Et j'arrive pas à caster :S
Je crois que c'est impossible de caster un char en unsigned char...
 

Lakh92

Membre Actif
Inscrit
24 Decembre 2009
Messages
118
Reactions
0
#12
NicoMasterChief a dit:
J'ai déjà essayé ça quand même^^
La fonction recv() provoque une erreur car elle veut un tableau de char, pas un tableau d'unsigned char. Et j'arrive pas à caster :S
Je crois que c'est impossible de caster un char en unsigned char...
C'est l'inverse que tu veux faire, non?

Il faut que tu utilises reinterpret_cast<> pour pouvoir effectuer un cast de deux types non "reliés", si mes souvenirs sont bons.
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#13
Je n'ai pas essayé, mais cela me surprendrait que tu ne puisses pas caster de char en unsigned char, vu que leur représentation mémoire est la même.

Quelle syntaxe utilises-tu, et quelle erreur obtiens-tu ?
 

Sorrow

Membre Actif
Inscrit
5 Mai 2012
Messages
376
Reactions
26
#14
Bonjour,

Dans le cadre d'un Proxy MITM pour dofus qui fait le transite Client <-> Server, quand la taille de mon buffer est plus grande que le packet reçus, je reçois des tas de données inutile.
(Je poste ici car les source du début sont identique, sa peut donc aider ;))

Server -> Proxy
Rapport wireshark :

http://pastebin.com/QhAP1rkg

Puis le hexdump sur le proxy :

http://img11.hostingpics.net/pics/879963ProxyD.png

Proxy -> Dofus
Et enfin, le rapport WPE Pro sur DofusMod.exe:

http://pastebin.com/JHgMU9Mm

Et si cela peut aider, le code source : http://pastebin.com/iQK48Ce6
Comme vous pouvez le voir DEFAULT_BUFLEN est à 8192
Et j'ai intégré des sizeof() un peut partout au cas où...

PS : J'ai une version plus élaborer en PHP qui fonctionne, je m'en suis inspirer pour le code C++, et faudrait que je test avec la lib Net de Qt
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#15
Code:
void* ecoute(void* data)                                                                        // fonction thread
{
    parametres_socket* p = static_cast<parametres_socket*>(data);
    connect(p->sock, (SOCKADDR *)&p->sin, sizeof(p->sin));                                      // connexion au socket
    while (1)
    {
        int i=recv(p->sock,p->buffer,sizeof(p->buffer), 0);                                     // réception et stockage dans la variable i
        unsigned char p->buffer[8192] = reinterpret_cast<unsigned char>(p->buffer[8192]);            // ligne de l'erreur !
        cout<<"Nombre d'octets recus : "<<i<<endl;                                              // affichage du nombre d'octets reçus
        for (int j=0;j<i;j++)                                                                   // affichage des bytes reçus
        {
            cout<<"0x"<<p->buffer[j]<<" ";
        }
        cout<<endl;
    }
    return NULL;
}
Erreur : expected initializer before '->' token

Manque un truc avant le '->', mais je sais pas quoi :S
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#16
Donc personne ne sait comment résoudre l'erreur ? :/
 
A

Anonymous

Invité
#17
Je t'aurai bien aidé pais je comprend rien au C
 
Haut Bas