2017-08-16 2 views
0

Vérifiez ces deux programmes client client simples. Comme dans la première condition. Le client transmet des données au serveur et Vies Versa est possible. mais quand j'essaie de faire simultanément ou consécutive. Ils sont bloqués en condition de course. méthodeDonnées simples Transmission dans Boost :: asio?

#include <iostream> 
#include <boost/asio.hpp> 

void handler(boost::system::error_code &error_code, size_t size) 
{ 
} 

void read(boost::asio::ip::tcp::socket &socket1, boost::system::error_code error_code) 
{ 
    boost::asio::streambuf streambuf; 
    boost::asio::read(socket1, streambuf, error_code); 

    std::istream streambuf1(&streambuf); 
    std::string string; 
    streambuf1 >> string; 
    std::cout << string << std::endl; 
} 

void write(boost::asio::ip::tcp::socket &socket1, boost::system::error_code error_code) 
{ 
    std::string string("hello"); 
    boost::asio::write(socket1, boost::asio::buffer(string), error_code); 
} 

int main() 
{ 
    boost::asio::io_service io_service; 
    boost::asio::ip::tcp::socket socket1(io_service); 
    boost::asio::ip::tcp::acceptor acceptor(io_service, 
              boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 9999)); 
    boost::system::error_code error_code; 
    acceptor.accept(socket1, error_code); 
    if (error_code != nullptr) 
    { 
     std::cerr << error_code.message() << std::endl; 
    } 
    write(socket1, error_code); 
    read(socket1, error_code); 

    io_service.run(); 
    return 0; 
} 

est ma façon erronée ou dois-je stimuler l'utilisation :: asio :: async_write() pour la transmission de retour:

programme client:

#include <boost/asio.hpp> 

void read(boost::asio::ip::tcp::socket& socket1, boost::system::error_code error_code) 
{ 
    boost::asio::streambuf streambuf; 
    boost::asio::read(socket1, streambuf, error_code); 

    std::istream streambuf1(&streambuf); 
    std::string string; 
    streambuf1 >> string; 
    std::cout << string << std::endl; 
} 

void write(boost::asio::ip::tcp::socket& socket1, boost::system::error_code error_code) 
{ 
    std::string string("hello"); 
    boost::asio::write(socket1, boost::asio::buffer(string), error_code); 
} 

int main(int argc, char *argv[]) 
{ 
    boost::asio::io_service io_service; 
    boost::asio::ip::tcp::socket socket1(io_service); 
    boost::asio::ip::tcp::resolver resolver(socket1.get_io_service()); 
    boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), "9999"); 
    boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); 
    boost::asio::connect(socket1, iterator); 
    boost::system::error_code error_code; 

    read(socket1, error_code); 
    write(socket1, error_code); 
    io_service.run(); 
    return 0; 
} 

C'est simple programme de serveur et quatrième données.

+0

Quel est exactement le problème? Est-ce que ça plante? Est-ce que quelque chose ne fonctionne pas? "coincé dans l'état de la course" Quand cela se produit-il exactement? S'il vous plaît fournir plus d'informations. – Blacktempel

+0

C'est le problème. Ça ne plante pas. Le serveur et le client ne se transmettent pas de données. si je règle Communication Simplex (Serveur à Client || Client vers Serveur) les données sont en cours de transmission, mais comme j'ai utilisé les deux (Fonction Écriture et Lecture), rien ne se passe. ni les données n'envoient ni ne reçoivent sur les deux côtés. Alors que le problème. –

+0

S'il vous plaît n'oubliez pas de [accepter/upvote une réponse si elle a résolu votre question.] (Https://stackoverflow.com/help/someone-answers) – Blacktempel

Répondre

0

Si vous regardez dans la documentation de boost::asio::streambuf vous pouvez déjà repérer dans la section Examples ce que vous avez probablement fait de mal.

Tout d'abord, votre client se connecte à ... quelle adresse? 0.0.0.0? Vous devriez vraiment spécifier où il devrait se connecter. Cela fait une erreur, car vous ne gérez pas le cas d'erreur sur se connecter. Peut-être que vous n'avez pas fourni le bon code à reproduire?

Si vous ne voulez pas de plantages aléatoires, gérez tous les cas d'erreur possibles.
Boost vous aide déjà avec le paramètre d'erreur.

boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), "9999"); //0.0.0.0 ? 

//--- 

boost::asio::ip::tcp::resolver::query query("localhost", "9999"); //Specify where to connect 
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); 
boost::asio::connect(socket1, iterator); 

Maintenant que vous pouvez vous connecter à votre partenaire distant, vous souhaitez également recevoir le message envoyé.

boost::asio::streambuf streambuf; 

//Reserve some bytes for data (here adjusted for your message 'hello') 
boost::asio::streambuf::mutable_buffers_type buf = streambuf.prepare(5); //Refer to documentation 
auto sizeReceived = boost::asio::read(socket1, buf, error_code); 
//Received bytes are 'committed' 
streambuf.commit(sizeReceived); 

std::istream streambuf1(&streambuf); 
std::string string; 
streambuf1 >> string; 
std::cout << string << std::endl; //'hello' 

Parallèlement à cela, c'est le code complet que je l'ai utilisé pour tester votre échantillon (ne me dérange pas la classe de base):

class Runable 
{ 
public: 
    virtual void Run() = 0; 
}; 

class Client : public Runable 
{ 
public: 
    void Run() override 
    { 
     boost::asio::io_service io_service; 
     boost::asio::ip::tcp::socket socket1(io_service); 
     boost::asio::ip::tcp::resolver resolver(socket1.get_io_service()); 
     boost::asio::ip::tcp::resolver::query query("localhost", "9999"); //Specify where to connect 
     boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); 
     boost::asio::connect(socket1, iterator); 
     boost::system::error_code error_code; 

     read(socket1, error_code); 
     write(socket1, error_code); 
     io_service.run(); 
    } 

private: 
    void read(boost::asio::ip::tcp::socket& socket1, boost::system::error_code error_code) 
    { 
     boost::asio::streambuf streambuf; 

     boost::asio::streambuf::mutable_buffers_type buf = streambuf.prepare(5); //Refer to documentation 
     auto sizeReceived = boost::asio::read(socket1, buf, error_code); 
     streambuf.commit(sizeReceived); 

     std::istream streambuf1(&streambuf); 
     std::string string; 
     streambuf1 >> string; 
     std::cout << __FUNCTION__ << " # " << string << std::endl; 
    } 

    void write(boost::asio::ip::tcp::socket& socket1, boost::system::error_code error_code) 
    { 
     std::string string("hello"); 
     boost::asio::write(socket1, boost::asio::buffer(string), error_code); 
    } 
}; 

class Server : public Runable 
{ 
public: 
    void Run() override 
    { 
     boost::asio::io_service io_service; 
     boost::asio::ip::tcp::socket socket1(io_service); 
     boost::asio::ip::tcp::acceptor acceptor(io_service, 
     boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 9999)); 
     boost::system::error_code error_code; 
     acceptor.accept(socket1, error_code); 
     if (error_code != nullptr) 
     { 
      std::cerr << error_code.message() << std::endl; 
     } 
     write(socket1, error_code); 
     read(socket1, error_code); 

     io_service.run(); 
    } 

private: 
    void read(boost::asio::ip::tcp::socket &socket1, boost::system::error_code error_code) 
    { 
     boost::asio::streambuf streambuf; 

     boost::asio::streambuf::mutable_buffers_type buf = streambuf.prepare(5); 
     auto sizeReceived = boost::asio::read(socket1, buf, error_code); 
     streambuf.commit(sizeReceived); 

     std::istream streambuf1(&streambuf); 
     std::string string; 
     streambuf1 >> string; 
     std::cout << __FUNCTION__ << " # " << string << std::endl; 
    } 

    void write(boost::asio::ip::tcp::socket &socket1, boost::system::error_code error_code) 
    { 
     std::string string("hello"); 
     boost::asio::write(socket1, boost::asio::buffer(string), error_code); 
    } 
}; 

int wmain(int argv, wchar_t **args) 
{ 
    std::thread st = std::thread([]() { Server s; s.Run(); }); 
    std::thread ct = std::thread([]() { std::this_thread::sleep_for(std::chrono::milliseconds(100)); Client c; c.Run(); }); 

    st.join(); 
    ct.join(); 

    return 0; 
} 

Lorsque la sortie est :

Output

S'il vous plaît noter également, que boost::asio::read ne reviendra pas à moins que le tampon fourni soit plein.

+0

Notez que ce n'est qu'un test rapide. Vous devez vous assurer que le serveur accepte une connexion avant l'appel de 'connect' sur le côté client. (Ici fait avec un sommeil sur le fil actuel) – Blacktempel