C/C++ [Résolu][C++][Full Socket] Thread, Parser, Reader

Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#1
Bonjour à tous,

Je travaille actuellement sur la conception d'un bot pour D2 de type socket en C++.
J'ai actuellement coder la connexion au serveur d'authentification, jusqu'ici tout va bien, le bot se connecte correctement.
Code utilisé pour se connecter.
Code:
// MAIN.CPP

#include <iostream>

#include "Network.hpp"
#include "Exception.hpp"

#define PORT (5555)
#define IP ("213.248.126.39")


int main()
{
  try
    {
      Network *n;

      n = new Network(PORT, IP);
      std::cout << "Tentative de connection sur : " << n->getIp() << ":" << n->getPort() << std::endl;
      n->initialize();
      n->connection();
      n->process();
      n->closeSocket("");
    }
  catch (Except *e)
    {
      std::cerr << "[ERROR LOG] " << e->what() << std::endl;
    }
}
Code:
// NETWORK.CPP

#include "Network.hpp"
#include "Exception.hpp"
#include <stdio.h>

Network::Network(const int p, const std::string &_ip) : ip(_ip)
{
  this->port = p;
}

Network::~Network()
{
}

void Network::initialize()
{
  struct protoent *pe;
  int errsv;

  pe = getprotobyname("TCP");
  if (!pe)
    {
      errsv = errno;
      std::string error = "Error on getprotobyname [";
      error += strerror(errsv);
      error += "]";
      throw Except(error);
    }
  this->socketFd = socket(AF_INET, SOCK_STREAM, pe->p_proto);
  if (this->socketFd == -1)
    {
      errsv = errno;
      std::string error = "Error on socket [";
      error += strerror(errsv);
      error += "]";
      throw Except(error);
    }
}

void Network::connection()
{
  struct sockaddr_in sin;
  int errsv;

  sin.sin_family = AF_INET;
  sin.sin_port = htons(this->port);
  sin.sin_addr.s_addr = inet_addr(this->ip.c_str());
  int ret = connect(this->socketFd, (struct sockaddr *)&sin, sizeof(sin));
  if (ret == -1)
    {
      errsv = errno;
      std::string error = "Error on connect [";
      error += strerror(errsv);
      error += "]";
      this->closeSocket(error);
      throw Except(error);
    }
  std::cout << "Connection to the server successfully established" << std::endl;
}

void Network::process()
{
}

int Network::getPort() const
{
  return (this->port);
}

const std::string &Network::getIp() const
{
  return (this->ip);
}

void Network::closeSocket(const std::string &e)
{
  if (close(this->socketFd) == -1)
    {
      std::string err = e;
      err += "\nError on close [";
      int errsv = errno;
      err += strerror(errsv);
      err += "]";
      throw Except(err);
    }
}

// NETWORK.HPP


#ifndef NETWORK_HPP__
#define NETWORK_HPP__

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string>
#include <iostream>

#include <string.h>

class Network
{
private :
  int socketFd;
  int port;
  const std::string ip;

public :
  Network(const int, const std::string &);
  ~Network();

  void			initialize();
  void			connection();
  void			process();
  void			closeSocket(const std::string &);

  int			getPort() const;
  const std::string	&getIp() const;
};

#endif

Si vous avez des sugestions / remarques, n'hésiter pas.

Mais maintenant se pose le probleme du thread et j'aurais quelque question à vous poser :
- est-il obligatoire de threader la connexion ?
- comment si prendre ?

Pour le moment j'ai testé avec un simple recv et j'ai réussis à récuperer le premier paquet (id = 1) mais je me demandais si utiliser recv était la meilleure solution ou si il y avait mieux à faire (utiliser select() et/ou la lib pthread ?)

Voici mon code utilisé pour lire les paquets et récupérer l'id.
Code:
  unsigned char buffer[8192 + 1];

  int len = recv(this->socketFd, buffer, 5000, 0);
  if (len > 0)
    {
      buffer[len] = 0;
      std::cout << "taille lu : " << len << std::endl;
      short int header = (unsigned char)buffer[0] << 8 | (unsigned char)buffer[1];
      int id = header >> 2;
      std::cout << "id : [" << id << "]" << std::endl;
      std::cout << "===========MESSAGE=============" << std::endl;
      for (int j=0;j<len;j++)
        {
          printf("%02x ",(unsigned char)buffer[j]);
        }
      std::cout << std::endl;
      std::cout << "===============================" << std::endl;
    }
Et le résultat obtenue en console :


Merci d'avance,
Cordialement,
Kangogoo.

Ps : comme vous pouvez le constater je code sous Linux (avec emacs et g++)
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
Reactions
2
#2
Re: [C++][Full Socket] Threader la connexion

Tu devrais utiliser un framework pour te simplifier la vie (boost ou Qt)
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#3
Re: [C++][Full Socket] Threader la connexion

Je ne vois pas en quoi utiliser boost ou Qt me simplifierai la tache ?
Peux-tu étayer tes propos stp ?
 
Inscrit
27 Aout 2012
Messages
264
Reactions
0
#4
Re: [C++][Full Socket] Threader la connexion

Pour Qt, c'est possible de faire sans, si tu tiens au C++ pur.
En revanche, je te conseille Boost aussi, il est super complet et peut t'aider pour les threads.

Je ne l'ai jamais utilisé (j'avoue) mais je sais que c'est presque un incontournable.
J'ai trouvé ce post sur StackOverflow qui explique assez bien pourquoi Boost, c'est la vie.
http://stackoverflow.com/a/4682398
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#5
Re: [C++][Full Socket] Threader la connexion

J'avais répondu, mais à cause ma connexion, mon message s'est perdu, et j'ai pas envie de le refaire en entier, alors ce sera succinct.

Je te conseille de faire au moins un thread séparé pour le socket avec deux files de réception et d'envoi, comme ça tu peux faire une boucle (dans le cas d'un seul thread) qui envoie le cas échéant les trucs stockés dans la file d'envoi et qui met ce qu'il reçoit (avec des socket non bloquants ou un select) dans la file de réception. Tu as un autre thread qui récupère les paquets reçus et choisit ceux à envoyer.

Ajout : Je suis pas trop pour utiliser Qt ou Boost pour un truc aussi simple. Plus on utilise de trucs compliqués, moins on sait ce qu'on fait.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#6
Re: [C++][Full Socket] Threader la connexion

Labo a dit:
Je te conseille de faire au moins un thread séparé pour le socket avec deux files de réception et d'envoi
Quand tu dis deux "files de réception et d'envoi", tu entends deux files de réceptions et deux files de d'envoi ou une file de réception et une file d'envoi (donc deux files au totales) ?

Labo a dit:
comme ça tu peux faire une boucle (dans le cas d'un seul thread)
un simple while (socket.connected() == true) ?

Labo a dit:
qui envoie le cas échéant les trucs stockés dans la file d'envoi et qui met ce qu'il reçoit (avec des socket non bloquants ou un select) dans la file de réception.
Tu parles de plusieurs sockets si j'ai bien compris mais je ne vois pas bien comment tu peux utiliser plusieurs socket ?

Labo a dit:
Tu as un autre thread qui récupère les paquets reçus et choisit ceux à envoyer.
Donc un thread qui s'occupe de recevoir les données et un autre qui s'occupe d'écrire les paquets qu'on a besoin d'envoyer au jeu pour réaliser des actions (comme la connection, choix du personnage, etc)

Labo a dit:
Ajout : Je suis pas trop pour utiliser Qt ou Boost pour un truc aussi simple. Plus on utilise de trucs compliqués, moins on sait ce qu'on fait.
Je suis plutôt de cet avis aussi, mais je vais quand même jeter un oeil chez Boost pour voir comment ils utilisents les sockets/threads de leurs coté.

Cordialement,
Kangogoo.
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
Reactions
2
#7
Re: [C++][Full Socket] Threader la connexion

Je suis pas trop pour utiliser Qt ou Boost pour un truc aussi simple. Plus on utilise de trucs compliqués, moins on sait ce qu'on fait.
Remarque pas vraiment pertinente (surtout quand on ne code pas avec la/les frameworks en question?)
Faire une boucle de reception je crois que tout le monde sait plus ou moins faire, je ne vois pas pourquoi il faudrait réinventer la roue à chaque fois que l'on veut avancer: là c'est pareil, les ingénieurs de chez Qt, ont optimisés leurs algorithmes et je pense que le fait d'utiliser ce framework jouera en ta faveur quand tu confrontera au principe de reflexion utilisé par @kama dans les D2O/I (entre autres, car il faut voir un peu plus loin que la connection....) . Si tu es un puriste du c++ continues comme ca mais sache que c'est un langage extrêmement modulaire (à ne pas confondre avec modulable) car seul il n'est pas capable de t'apporter de fonctionnalités intéressantes (toutes proportions gardées avec d'autres langages évidemment.)

Je ne connais pas suffisamment boost pour t'en parler même si je vois que cela n'a pas déranger les autres personnes qui sont dans le même cas que moi de t'en parler :troll: :)

Edit: Je me suis rendu compte en relisant mon message qu'il pouvait sembler être écrit sur un ton agressif et/ou arrogant ce qui est bien évidemment aux antipodes du message que je cherchais à faire passer dans cette réponse.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#8
Re: [C++][Full Socket] Threader la connexion

Gohu a dit:
Faire une boucle de reception je crois que tout le monde sait plus ou moins faire, je ne vois pas pourquoi il faudrait réinventer la roue à chaque fois que l'on veut avancer: là c'est pareil, les ingénieurs de chez Qt, ont optimisés leurs algorithmes et je pense que le fait d'utiliser ce framework jouera en ta faveur quand tu confrontera au principe de reflexion utilisé par @kama dans les D2O/I (entre autres, car il faut voir un peu plus loin que la connection....) .
Tu penses qu'il est préférable de faire une gui avec Qt et d'utiliser directement Qt pour gérer tout ce qui thread et gestion des données en "arrière-plan" (en mode non bloquant quoi) ? Ou bien tu penses a tout autre chose ?

Cordialement,
Kangogoo.
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
Reactions
2
#9
Re: [C++][Full Socket] Threader la connexion

En fait je vais te dire tu as pas besoin de faire que thread avec la classe QSocket car Qt s'occupe de tout <3
Ce framework propose tellement plus de truc que ca en plus (indépendamment de la GUI) qui pourront t'être utile pour terminer ton projet car la on parle de la connection mais dans une semaine tu vas être beaucoup plus avancé et tu fera face à d'autres problèmes qui seront solvables aussi par Qt (pas uniquement bien sûre!) mais crois moi c'est un "investissement" à long terme. En gros fait ton projet avec Qt
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#10
Re: [C++][Full Socket] Threader la connexion

- Non, une de chaque.
- Le mieux serait d'ajouter une condition d'arrêt qui te permet d'arrêter le thread depuis l'extérieur, mais je m'y connais pas trop en threads en C++.
- Non, un seul socket, je désignais dans sa globalité l'univers de tous les sockets non bloquants ayant existé, existant, qui existeront, qui auraient pu exister ou qui pourraient exister dans l'ensemble des univers alternatifs ayant existé, ...
- Là, tu fais comme tu veux, tu peux aussi faire une boucle qui gère les paquets, et dans un autre thread l'IA.

Moi je trouve que Qt c'est pas du C++. Enfin, j'ai programmé une semaine avec Qt, donc je peux pas trop parler. Mais c'est vrai que Boost c'est bien.

Ce que j'ai voulu dire, c'est que c'est pas la peine de lire des dizaines de pages de doc puis passer 1h ou 2 sur stack exchange (ou sur Cadernis) quand on peut faire ça soi-même avec ce qu'on sait en 5 minutes maximum.
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
Reactions
2
#11
Re: [C++][Full Socket] Threader la connexion

Ce que j'ai voulu dire, c'est que c'est pas la peine de lire des dizaines de pages de doc puis passer 1h ou 2 sur stack exchange (ou sur Cadernis) quand on peut faire ça soi-même avec ce qu'on sait en 5 minutes maximum.
C'est aussi pourquoi je dis que Qt est un investissement à long terme qui va te permettre d'avancer plus vite sans te prendre la tête avec des problèmes d'optimisations et autre. AS3 est un langage de très haut niveau et par conséquent il utilise des fonctions de très haut niveau qui sont pour certaines assez complexes à mimer (je pense notamment aux d2o). Qt peut te permettre de palier à ce problème de façon efficace. Après tu peux aussi aller recoder la std si ca te chante mais je vois pas vraiment l'intérêt de se priver de choses qui pourraient t'aider (sauf si tu aimes te faire mal?)
 
Inscrit
23 Novembre 2013
Messages
26
Reactions
0
#12
Re: [C++][Full Socket] Threader la connexion

Stop la battle

Qt, est un outil/framework, multi-platforme, permettant d'utiliser tout le potentiel du C++, en utilisant des outils haut niveau, pour des classes dont tout le monde a besoin, et qui sont chiantes à coder.

Pour ce qui est thread, et boucle, Qt possède sa propre boucle que tu verras jamais, donc pas besoin la creer toi meme, il existe ce que Boost et Qt appellent des SLOTS, qui sont appelés en cas d'événements (ex: ton socket vient de recevoir des données). Ainsi, pas besoin de faire un systeme manuel de liste d'attente

Boost, est plus léger que Qt, mais Qt possède son propre IDE, et permet de creer des interfaces graphiques bien plus facilement. Sans compter que Qt possède une documentation extrêmement bien expliquée et claire, des fonctions plus intuitives et spécialisées que Boost, et est activement mis à jour par Nokia.

PS: Utiliser du c++ pour coder ce genre de choses sans librairie autre que la STL, c'est prendre du retard pour rien, les autres languages proposent ce qu'offre Boost/Qt, par défaut. C++ avec la STL, n'est plus que utilisé pour des calculs brutes, ou par question d'optimisations EXTREMES
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
Reactions
2
#13
Re: [C++][Full Socket] Threader la connexion

Dire que tout le monde croyait que nokia n'existait plus
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#15
Re: [C++][Full Socket] Threader la connexion

Je suis assez d'accord avec toi, AnonymHax :p
C'est vrai qu'à force de programmer en Python, j'oublie que la stdl ne contient presque rien.
 
Inscrit
1 Mars 2014
Messages
120
Reactions
0
#16
Re: [C++][Full Socket] Threader la connexion

Boost va être intégré au standard c++ :)
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#17
Re: [C++][Full Socket] Threader la connexion

<3
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#18
Re: [C++][Full Socket] Threader la connexion

Merci à tous pour votre aide et vos suggestions.
J'ai donc regarder du coté de Qt pour voir comment était utilisé les sockets pour savoir si oui ou non j'allais m'orienter vers Qt pour mon bot. Et il s'avère que c'est beaucoup plus simple d'utiliser les fonctions pré-faites de Qt que de tout faire sois-même à la main.
J'ai donc recommencer la connexion socket au serveur et pour l'instant tout semble bien se porter (simple connexion sur l'ip et le port du jeu avec un GUI pour se connecter/déconnecter).
Il ne me reste plus qu'à retranscrire la partie qui réceptionne les paquets lu (recvData) et je pourrais m'attaquer à la partie reader/write et traitement des packets.

Cordialement,
Kangogoo.

Ps : j'ai cru comprendre que le parser de toons était fonctionnel depuis plusieurs année maintenant et je me demandais le quel était le plus viable à transcrire en C++ : celui de toons ou un autre comme celui de RaphyTheGeek ?
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
Reactions
2
#19
Re: [C++][Full Socket] Threader la connexion

Fais ton parseur avec Qt c'est beaucoup plus simple avec les QDataStream
Edit: je viens de me souvenir que si tu veux commencer tu as celui de Sorrow fait en c++ c'est celui que j'avais utilisé pour commencer
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#20
Re: [C++][Full Socket] Threader la connexion

Fais attention à comment tu reçois les paquets ! Soit tu fais comme dans les sources avec un buffer de 8192 Bytes, soit tu fais comme moi qui ne reçois que le header pour avoir la taille puis reçois exactement la taille du paquet.
 
Haut Bas