Первые данные среды: Windows 7, c: \ boost (1.55.0), Microsoft Visual C ++ 2010 Express (SP1)
Вот самая простая функциональная версия клиента / сервера, о которой вы можете подумать, используя новые линии с окончанием строки в качестве способа транспортировки (не обращайте внимания на отсутствие ограничений и время ожидания, пожалуйста!)
Сервер ждет, пока клиент не отправит "f\n"
, а затем отправляет обратно обрезанные строки из локального текстового файла обратно клиенту. Самая последняя строка содержит только точку (.), Которая указывает на конец передачи (не считая того факта, что в файле может быть точка).
Вывод на сервер показывает, что все строки отправляются обратно клиенту. Клиент, однако, показывает, что отсутствуют некоторые строки.
Я не вижу, где есть возможность для передачи пропустить данные.
Вот полнофункциональный код сервера. Постройте его и запустите на сервере без аргументов.
#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 )
Функция в версии клиента неверна. Использует буферизованный ввод, который ест больше, чем должен.
Это не лучшая версия, но вместо текущего кода клиента:
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" ;
}