boost :: asio:数据损坏 [英] boost::asio : data corruption

查看:74
本文介绍了boost :: asio:数据损坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我介绍了一个用 Asio 编写的简单客户端和服务器,以显示可能是错误的内容. 客户端反复向服务器发送长度为102的固定字符串,然后服务器检查该字符串 是正确的,如果不正确,则会写一条错误消息,然后退出.

I present a simple client and server written in Asio to show something that might be a bug. client repeatedly sends a fixed string of length 102 to the server and server checks the string to be correct and writes an error message if not so and exits.

该代码已在debian 7(amd64)中编译并运行.
我的处理器有2个内核
增强版是1.55

The code is compiled and run in debian 7 (amd64)
my processor has 2 cores
boost version is 1.55

运行服务器和客户端时,发送几千个数据包后 收到错误的数据包.(可能需要重复测试几次)

when running server and client, after a few thousand packets are sent a wrong packet is received.(it may be required to repeat the test a few times)

出什么问题了?

Makefile

CXX=g++
LIBS = -lboost_thread -lboost_filesystem -lboost_system

all: server asyncclient
server: server.o
    $(CXX) $(LIBS) server.o -o server
asyncclient: asyncclient.o
    $(CXX) $(LIBS) asyncclient.o -o asyncclient
server.o: server.cpp
    $(CXX) -c server.cpp
asyncclient.o: asyncclient.cpp
    $(CXX) -c asyncclient.cpp

server.cpp

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
using boost::asio::ip::tcp;
char teststr[]="1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n";
void session(tcp::socket* sock)
{
    boost::array<char, 102> buf;// 102 == sizeof(teststr)
    int i=0;
    try
    {
            for (;;)
            {
                    std::cout<<i++<<std::endl;
                    boost::system::error_code error;
                    size_t length = boost::asio::read(*sock, boost::asio::buffer(buf), error);
                    if (error == boost::asio::error::eof)
                            break; // Connection closed cleanly by peer.
                    else if (error)
                            throw boost::system::system_error(error); // Some other error.
                    if(strcmp(buf.data(), teststr)!=0)
                    {
                            std::cerr<<"error"<<std::endl;
                            std::cerr<<"    buf.data() = "<<
                                    std::string(buf.data(), buf.size())<<std::endl;
                            return;
                    }
            }
    }
    catch (std::exception& e)
    {
            std::cerr << "Exception: " << e.what() << "\n";
    }
}

int main()
{
    std::cerr<<"sizeof(teststr) = "<<sizeof(teststr)<<std::endl;//DEBUG
    boost::asio::io_service ios;
    tcp::acceptor a(ios, tcp::endpoint(tcp::v4(), 41000));
    tcp::socket sock(ios);
    a.accept(sock);
    boost::thread t(boost::bind(session, &sock));
    t.join();
}

asyncclient.cpp

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

using boost::asio::ip::tcp;

char teststr[]="1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n";

void handle_write(size_t num_bytes, boost::system::error_code e)
{
    static int i=0;
    if(!e)
    {
        std::cout<<i++<<std::endl;
    }
    else
    {
        std::cout<<"Error: "<<e.message()<<std::endl;
        exit(1);
    }
}

int main()
{
    boost::asio::io_service ios;

    tcp::resolver r(ios);
    tcp::resolver::query q(tcp::v4(), "127.0.0.1", "41000");
    tcp::resolver::iterator it = r.resolve(q);

    tcp::socket sock(ios);
    boost::asio::connect(sock, it);

    boost::thread t(boost::bind(&boost::asio::io_service::run,&ios));
    try
    {
        for(;;)
        {
            boost::asio::async_write(sock, boost::asio::buffer(teststr,102),
                    boost::bind(&handle_write,
                    boost::asio::placeholders::bytes_transferred,
                    boost::asio::placeholders::error));
        }
    }
    catch(std::exception& e)
    {
        std::cout<<"Exception: "<<e.what()<<std::endl;
    }
    t.join();
}

推荐答案

问题来自以下for循环:

the problem comes from the following for loop:

for(;;)
    {
        boost::asio::async_write(sock, boost::asio::buffer(teststr,102),
                boost::bind(&handle_write,
                boost::asio::placeholders::bytes_transferred,
                boost::asio::placeholders::error));
    }

async_write操作可能在完成之前开始 不允许使用以前的async_write.
REF: async_write

an async_write operation may be begin before the completion of previous async_write which is not allowed.
REF: async_write

正确的方法是消除for循环并调用async_write 在handle_write函数中:

the correct way is to eliminate the for loop and call async_write in the handle_write function:

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

using boost::asio::ip::tcp;

char teststr[]="1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n";

void handle_write(tcp::socket* sock, size_t num_bytes, boost::system::error_code e)
{
    static int i=0;
    if(!e)
    {
        std::cout<<i++<<std::endl;
        boost::asio::async_write(*sock, boost::asio::buffer(teststr,102),
                boost::bind(&handle_write, sock,
                    boost::asio::placeholders::bytes_transferred,
                    boost::asio::placeholders::error));
    }
    else
    {
        std::cout<<"Error: "<<e.message()<<std::endl;
        exit(1);
    }
}

int main()
{
    boost::asio::io_service ios;

    tcp::resolver r(ios);
    tcp::resolver::query q(tcp::v4(), "127.0.0.1", "41000");
    tcp::resolver::iterator it = r.resolve(q);

    tcp::socket sock(ios);
    boost::asio::connect(sock, it);

    boost::thread t(boost::bind(&boost::asio::io_service::run,&ios));
    boost::asio::async_write(sock, boost::asio::buffer(teststr,102),
            boost::bind(&handle_write, &sock,
                boost::asio::placeholders::bytes_transferred,
                boost::asio::placeholders::error));
    t.join();
}

这篇关于boost :: asio:数据损坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆