boost :: asio:数据损坏

时间:2014-04-15 04:37:21

标签: c++ boost-asio

我提供了一个用 Asio 编写的简单客户端和服务器,以显示可能存在错误的内容。 客户端重复向服务器发送长度为102的固定字符串,服务器检查该字符串 要正确,如果不是这样就写一条错误信息并退出。

代码编译并在debian 7(amd64)中运行 我的处理器有2个核心
提升版是1.55

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

问题是什么?

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();
}

1 个答案:

答案 0 :(得分:2)

问题来自以下for循环:

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是不允许的。
参考: async_write

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

#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();
}