Zufälliges EOF im Boost-Asio im Multi-Thread

Ich bin ziemlich neu, um Asio zu steigern, und ich erlebezufälliges Dateiende in einem Multi-Thread-Server.

Ich könnte mein Problem in diesem kleinen Beispiel reproduzieren:

Server:

Dies ist ein einfacher Echoserver. Das Protokoll ist einfach:

(1) Eine Client-Verbindung(2) Der Server liest ein Byte. Dieses Byte ist die Länge der Zeichenfolge, die gelesen und zurückgesendet werden soll.(3) Der Server liest N Bytes.(4) Der Server sendet N + 1 Bytes an den Client zurück und geht zurück zu (2).

Wenn der Client die Verbindung trennt Eine EOF wird in (3) erfasst und die Handler-Schleife wird gestoppt.

class MySocket{
public:
    char buffer[257];
    boost::asio::ip::tcp::socket socket;
    MySocket(boost::asio::io_service*ios):socket(*ios){}
    ~MySocket(){}
};

//Handlers

void readN(std::shared_ptr<MySocket>server,const boost::system::error_code&ec);

//(4)
void echo(std::shared_ptr<MySocket>server,const boost::system::error_code&ec){
    if(ec){
        throw std::exception(("This is NOT OK: "+ec.message()).c_str());}
    size_t n=server->buffer[0]&0xFF;
    std::cout<<std::string(server->buffer+1,n)<<std::endl;
    boost::asio::async_write(server->socket,boost::asio::buffer(server->buffer,n+1),boost::bind(readN,server,boost::asio::placeholders::error));}

//(3)
void read(std::shared_ptr<MySocket>server,const boost::system::error_code&ec){
    if(ec){
        throw std::exception(("This is OK: "+ec.message()).c_str());}
    size_t n=server->buffer[0]&0xFF;
    boost::asio::async_read(server->socket,boost::asio::buffer(server->buffer+1,n),boost::bind(echo,server,boost::asio::placeholders::error));}

//(2)
void readN(std::shared_ptr<MySocket>server,const boost::system::error_code&ec){
    if(ec){
        throw std::exception(("This is also NOT OK: "+ec.message()).c_str());}
    boost::asio::async_read(server->socket,boost::asio::buffer(server->buffer+0,1),boost::bind(read,server,boost::asio::placeholders::error));}

//Server

void serve(boost::asio::io_service*ios){
    for(;;){
        try{ios->run();break;}
        catch(const std::exception&e){std::cout<<e.what()<<std::endl;}}}

//(1)
void accept(boost::asio::io_service*ios,boost::asio::ip::tcp::acceptor*acceptor,std::shared_ptr<MySocket>server,const boost::system::error_code&ec){
    if(server.get()!=nullptr){
        server->socket.set_option(boost::asio::ip::tcp::no_delay(true));
        readN(server,ec);}
    server.reset(new MySocket(ios));
    acceptor->async_accept(server->socket,boost::bind(accept,ios,acceptor,server,boost::asio::placeholders::error));}

int main(){
    boost::asio::io_service ios;
    boost::asio::ip::tcp::acceptor acceptor(ios,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),1207));
    boost::asio::io_service::work work(ios);
    accept(&ios,&acceptor,nullptr,boost::system::error_code());
//    std::thread other(boost::bind(serve,&ios));
    serve(&ios);
    acceptor.close();
    ios.stop();
//    other.join();
    return 0;}

Klient:

Der Client stellt eine Verbindung zum Server her und sendet 1000 Zeichenfolgen.

int main(){
    try{
        boost::asio::io_service ios;
        boost::asio::ip::tcp::socket socket(ios);
        boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string("127.0.0.1"),1207);
        socket.connect(endpoint);
        socket.set_option(boost::asio::ip::tcp::no_delay(true));
        char buf[257];
        for(size_t i=0;i<1000;++i){
            size_t n=(i%127)+1;
            buf[0]=(char)n;
            for(size_t j=0;j<n;++j){
                buf[j+1]=(char)('A'+(j+i)%26);}
            socket.send(boost::asio::buffer(buf,n+1));
            socket.receive(boost::asio::buffer(buf,1));
            if((buf[0]&0xFF)!=n){
                throw std::exception("Oups!");}
            socket.receive(boost::asio::buffer(buf+1,n));
            for(size_t j=0;j<n;++j){
                if(buf[j+1]!=(char)('A'+(j+i)%26)){
                    throw std::exception("Oups!");}}
            std::cout<<i<<": "<<std::string(buf+1,n)<<std::endl;}}
    catch(const std::exception&e){
        std::cout<<e.what()<<std::endl;}
    return 0;}

Wenn der Server nur einen Thread verwendet (der andere Thread ist kommentiert), gibt der Server die 1000 Zeichenfolgen korrekt wieder.

Wenn der Server den anderen Thread verwendet, wird eine EOF in (4) nach einer zufälligen Anzahl gedruckter Zeichenfolgen erfasst. Das sollte niemals passieren.

Ich habe versucht, alle asynchronen Anrufe mit einem Strang zu verbinden, aber es hat nicht funktioniert.Soweit ich sehen kann, gibt es keine Datenrennprobleme. Handler sollten nacheinander angerufen werden.

Was habe ich verpasst ?

Was ist die richtige Sprache für eine Multithread-Asio-Anwendung?

EDIT:

Ich habe ein paar Tests gemacht und es sieht so aus, als würde ich diese Zeile ersetzen

throw std::exception(("This is NOT OK: "+ec.message()).c_str());

mit:

std::cout<<"This is not OK: "<<ec.message()<<std::endl;

Der Server gibt die 1000 Zeilen korrekt wieder, auch wenn ich sehe, dass einige EOF-Werte einige Male fälschlicherweise als Argumente übergeben wurden.

Ich denke also, die Frage istwarum bekomme ich einen falschen boost :: asio :: error :: eof wenn der socket offensichtlich nicht geschlossen ist?

Dies wird nicht angegebenHier.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage