简单的客户端/服务器在传输中丢失线路(boost/Windows)



第一个环境数据:Windows 7、c:\boost(1.55.0)、Microsoft Visual c++2010学习版(SP1)

这是你能想到的最简单的客户端/服务器功能版本,使用新的线路末端线路作为运输方式(请忽略缺少限制和超时!)

服务器等待,直到客户端发送"fn",然后将本地文本文件中修剪后的行发回客户端。最后一行只有一个点(.),表示传输结束(忽略文件中可能有一个点的事实。)

问题出在哪里

服务器上的输出显示所有行都被发送回客户端。然而,客户端显示缺少一些行。

我看不出传输哪里有可能丢失数据。

这是功能齐全的服务器代码。构建它,并在不带参数的服务器上运行。

#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include <iostream>
#include <boost/asio.hpp>
void writeln( boost::asio::ip::tcp::socket& socket, const std::string& text )
{
    std::cout << "writeln " << text << "n" ;
    boost::system::error_code error ;
    boost::asio::write( socket, boost::asio::buffer( text + "n", text.length() + 1 ), boost::asio::transfer_all(), error );
}
bool readln( boost::asio::ip::tcp::socket& socket, std::string& text )
{
    try
    {
        boost::asio::streambuf response ;
        boost::asio::read_until( socket, response, "n" ) ;
        std::istream response_stream( &response ) ;
        std::getline( response_stream, text ) ;
        if ( text != "." )
            return true ;
    }
    catch( const std::exception& e )
    {
        std::cerr << e.what() << "n" ;
    }
    return false ;
}
static char* trim( char* line )
{
    size_t len = strlen( line ) ;
    while ( len > 0 && ( line[ len - 1 ] == ' ' || line[ len - 1 ] == 't' || line[ len - 1 ] == 'n' || line[ len - 1 ] == 'r' ))
        len-- ;
    line[ len ] = 0 ;
    return line ;
}
static void f( boost::asio::ip::tcp::socket& socket )
{
    std::string fname = "c:\f.txt" ;
    FILE* f = fopen( fname.c_str(), "r" ) ;
    if ( f != NULL )
    {
        char line[ 1024 ] ;
        while ( fgets( line, sizeof( line ), f ) != NULL )
            writeln( socket, trim( line )) ;
        fclose( f ) ;
    }
}
int main( int argc, char* argv[])
{
    try
    {
        boost::asio::io_service        io_service ;
        boost::asio::ip::tcp::acceptor acceptor( io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 8080 )) ;
        for (;;)
        {
            boost::asio::ip::tcp::socket socket( io_service ) ;
            std::string                  cmd ;
            acceptor.accept( socket ) ;
            while ( readln( socket, cmd ))
            {
                std::cout << cmd << "n" ;
                if ( cmd == "f" )
                    f( socket ) ;
                writeln( socket, "." ) ;
            }
        }
    }
    catch( const std::exception& e )
    {
        std::cerr << e.what() << "n" ;
    }
    return 0 ;
}

这是客户的代码。调用prog 127.0.0.1 f查看结果。

#include "stdafx.h"
#include <boost/asio.hpp>
#include <iostream>
void writeln( boost::asio::ip::tcp::socket& socket, const std::string& text )
{
    boost::system::error_code error ;
    boost::asio::write( socket, boost::asio::buffer( text + "n", text.length() + 1 ), boost::asio::transfer_all(), error );
}
bool readln( boost::asio::ip::tcp::socket& socket, std::string& text )
{
    try
    {
        boost::asio::streambuf response ;
        boost::asio::read_until( socket, response, "n" ) ;
        std::istream response_stream( &response ) ;
        std::getline( response_stream, text ) ;
        std::cout << "readln " << text << "n" ;
        if ( text != "." )
            return true ;
    }
    catch( const std::exception& e )
    {
        std::cerr << e.what() << "n" ;
    }
    return false ;
}
int main( int argc, char* argv[])
{
    if ( argc > 2 )
        try
        {
            boost::asio::io_service      io_service ;
            boost::asio::ip::tcp::socket socket( io_service ) ;
            std::string                  text ;
            socket.connect( boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( argv[ 1 ]), 8080 )) ;
            writeln( socket, argv[ 2 ]) ;
            while ( readln( socket, text ))
                std::cout << text << "n" ;
            return 0 ;
        }
        catch( const std::exception& e )
        {
            std::cerr << e.what() << "n" ;
            return 1 ;
        }
}

客户端版本中的bool readln( boost::asio::ip::tcp::socket& socket, std::string& text )函数不正确。使用缓冲io,吃得比应该吃的多。

这不是最好的版本,但不是客户当前的代码:

    while ( readln( socket, text ))
        std::cout << text << "n" ;

它可以做到:

    boost::asio::streambuf response ;
    for(;;)
    {
        boost::asio::read_until( socket, response, "n" ) ;
        std::istream response_stream( &response ) ;
        std::getline( response_stream, text ) ;
        if ( text == "." )
            break ;
        std::cout << text << "n" ;
    }

最新更新