From aecaf24c22013482de84ac6567249bec5ae7c78e Mon Sep 17 00:00:00 2001 From: dufourj Date: Sun, 1 May 2005 15:37:34 +0000 Subject: DataBuffer : Rajout du type de données Socket : Non-bloquant --- 2005/i/robert/src/socket/socket_text.cc | 198 +++++++++++++++++++++----------- 1 file changed, 134 insertions(+), 64 deletions(-) (limited to '2005/i/robert/src/socket/socket_text.cc') diff --git a/2005/i/robert/src/socket/socket_text.cc b/2005/i/robert/src/socket/socket_text.cc index 9c94509..da8a23b 100644 --- a/2005/i/robert/src/socket/socket_text.cc +++ b/2005/i/robert/src/socket/socket_text.cc @@ -26,29 +26,36 @@ #include "server_socket.hh" #include "address.hh" -#include "data/data_buffer.hh" #include #include +#include +#include + +/// Taille maximum du header +static const unsigned max_header_size = 10; /// Constructeur du serveur SocketText::SocketText (ServerSocket &ss) - : sendBufSize_ (0), recvTaille_ (0) +: recvBufPos_ (0), numMessageBuffer_ (0) { + headBuf_.resize (max_header_size); socket_ = ss.accept (); } /// Constructeur du serveur avec addresse SocketText::SocketText (ServerSocket &ss, Address &a) - : sendBufSize_ (0), recvTaille_ (0) +: recvBufPos_ (0), numMessageBuffer_ (0) { + headBuf_.resize (max_header_size); socket_ = ss.accept (a); } /// Constructeur du client SocketText::SocketText (const Address &a) - : sendBufSize_ (0), recvTaille_ (0) +: recvBufPos_ (0), numMessageBuffer_ (0) { + headBuf_.resize (max_header_size); // Création du socket socket_ = socket (AF_INET, SOCK_STREAM, 0); if (socket_ == -1) @@ -62,12 +69,16 @@ SocketText::SocketText (const Address &a) SocketText & SocketText::operator<< (const DataBuffer &d) { + // Copie du buffer DataBuffer db (d); + // Récupération de la taille du message unsigned size = db.size (); - std::vector v; - v.resize (size); - db.read ((uint8_t*) &v[0], size); - send (&v[0], size); + // Données du buffer + std::vector data (size); + // On y place les données dedans + db.read ((uint8_t*) &data[0], size); + // Encode les données et le places dans le buffer d'envoie + encode (&data[0], size, db.type ()); return *this; } @@ -75,92 +86,151 @@ SocketText::operator<< (const DataBuffer &d) SocketText & SocketText::operator>> (DataBuffer &d) { - std::vector v; - recv (v); - d.write ((uint8_t*) &v[0], v.size ()); + if (numMessageBuffer_ > 0) + { + // Récupération des informations du message qu'on veut retirer + unsigned int size = messList_.begin ()->size; + d.setType (messList_.begin ()->type); + // Récupération du message depuis le buffer + std::vector v (size); + std::memcpy (&v[0], &recvBuf_[0], size); + // Ecriture des données dans le buffer + d.write ((uint8_t*) &v[0], v.size ()); + // Suppression du message du buffer + recvBuf_.erase (recvBuf_.begin (), recvBuf_.begin () + size); + messList_.erase (messList_.begin ()); + bufferOldSize_ -= size; + bufferCurSize_ -= size; + recvBufPos_ -= size; + numMessageBuffer_--; + } return *this; } -/// Envoie d'un tableau de données (data) de taille size. +/// Envoie des données du buffer. int -SocketText::send (const char *data, const int size) +SocketText::send (void) { - int ss; int status; - int dataSend = 0; - // Encodage, ss = taille (message + header) - ss = size + encodeMsg (data, size); - do + status = ::send (socket_, &sendBuf_[0], sendBuf_.size (), MSG_NOSIGNAL); + if (status == -1 && errno != EWOULDBLOCK) { - status = ::send (socket_, &sendBuf_[0], ss - dataSend, MSG_NOSIGNAL); - dataSend += status; - } while (status >= 0 && size >= dataSend); - return status < 0 ? -1 : dataSend; + throw std::runtime_error ("Erreur de send de socket"); + } + if (status >= 0) + { + if (status != 0) + sendBuf_.erase (sendBuf_.begin (), sendBuf_.begin () + status); + return status; + } + return -1; } /// Encodage du message (rajout du header) -int -SocketText::encodeMsg (const char *data, const int size) +void +SocketText::encode (const char *data, const int size, + const DataBuffer::dataType_e type) { - // Création du header + // Création du header (1H4242H) std::ostringstream o; + // Rajout du type + if (!(o << type)) + throw std::runtime_error ("Erreur de convertion int -> string"); o << "H"; if (!(o << size )) throw std::runtime_error ("Erreur de convertion int -> string"); o << "H"; + // Recopie du header dans le buffer std::string s = o.str (); - int ss = s.size (); - // Re-Allocation du buffer d'envoye - sendBuf_.resize (ss + size); - // Copie du header - strncpy (&sendBuf_[0], s.c_str (), ss); - // Copie du message - strncpy (&sendBuf_[ss], data, size); - return ss; + std::string::const_iterator sEnd = s.end (); + unsigned int compt = 0; + std::string::const_iterator i = s.begin (); + // Ecriture d'un header de taille fixe + while (compt < max_header_size) + { + if (i != sEnd) + { + sendBuf_.push_back (*i); + i++; + } + else + sendBuf_.push_back ('H'); + compt++; + } + // Rajout des données dans le buffer + for (int i = 0; i < size; i++) + sendBuf_.push_back (data[i]); +} + +/// Décodage du header. +int +SocketText::decode (void) +{ + mess_t header; + header.type = (DataBuffer::dataType_e) std::atoi (&headBuf_[0]); + header.size = std::atoi (&headBuf_[2]); + messList_.push_back (header); + return header.size; } /// Reception de données dans un vecteur. -void SocketText::recv (std::vector &v) +bool +SocketText::recv () { // FIXME C'est KK int status; - static unsigned int pos = 0; - static unsigned int posHeader = 0; - // 0 : pas reçu, 1 : partiellement reçu, 2 : reçu - static int headerStatus = 0; + static unsigned int headerPos = 0; - // On n'a pas reçu la taille encore - if (headerStatus != 2) + // On n'a pas reçu encore de quoi faire un header + if (headerPos < max_header_size) { - // Récupération des données une par une. - do - { - status = ::recv (socket_, &headBuf_[posHeader], 1, MSG_NOSIGNAL); - if (headBuf_[posHeader++] == 'H') - headerStatus ++; - } while (status > 0 && headerStatus != 2); + status = ::recv (socket_, &headBuf_[headerPos], + max_header_size - headerPos, MSG_NOSIGNAL); + if (status == -1 && errno != EWOULDBLOCK) + throw std::runtime_error ("Erreur de send de socket"); + if (status > 0) + headerPos += status; } - // Récupération de la taille du message du header - if (headerStatus == 2 && recvTaille_ == 0) + // Décodage du header + if (headerPos == max_header_size) { - recvTaille_ = atoi (&headBuf_[1]); - pos = 0; - recvBuf_.resize (recvTaille_); + bufferOldSize_ = recvBuf_.size (); + bufferCurSize_ = bufferOldSize_ + decode (); + recvBuf_.resize (bufferCurSize_); + headerPos ++; } - if (recvTaille_) + // Récupération du message lui-même + if (headerPos > max_header_size) { - // Récupération du message lui-même - do - { - status = ::recv (socket_, &recvBuf_[pos], recvTaille_, - MSG_NOSIGNAL); - if (status > 0) - pos += status; - } while (status > 0 && pos < recvTaille_); - if (pos == recvTaille_) + status = ::recv (socket_, &recvBuf_[recvBufPos_], + bufferCurSize_ - recvBufPos_, MSG_NOSIGNAL); + if (status == -1 && errno != EWOULDBLOCK) + throw std::runtime_error ("Erreur de send de socket"); + if (status > 0) + recvBufPos_ += status; + if (recvBufPos_ == bufferCurSize_) { - v = recvBuf_; - headerStatus = posHeader = recvTaille_ = 0; + headerPos = 0; + numMessageBuffer_++; } } + return numMessageBuffer_ > 0; +} + +/// Changement du bloquant non/bloquant. +void +SocketText::nonblock (bool flag) +{ + // Récupération de l'ancien flag. + int old = fcntl (socket_, F_GETFL, 0); + if (old == -1) + throw std::runtime_error ("Erreur de fcntl"); + // Change le flag. + if (flag) + old |= O_NONBLOCK; + else + old &= ~O_NONBLOCK; + // Ecrit le nouveau flag. + if (fcntl (socket_, F_SETFL, old) == -1) + throw std::runtime_error ("Erreur de fcntl"); } -- cgit v1.2.3