먼저 환경 데이터를 푼다 버전의 부족한 부분을 무시하고 시간 초과는 무시하십시오!)간단한 클라이언트/서버 전송에 라인 (부스트/윈도우)
서버가 클라이언트가 "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 ;
}
}
KK
이없는 최고의 버전, 대신 클라이언트의 현재 코드의입니다. 나는 답을 알아. 'readln()'에서는 버퍼 된 클래스 (istream)를 사용하여 한 줄 이상을 먹지만, 모든 데이터를 소비하지는 않습니다. – Grzegorz
받은 모든 데이터를 소비하고 있으며, 사용자가 처리하는 'streambuf'에 의해 "소비"됩니다. 'streambuf'를 활성 상태로 유지하면 다음에 사용할 버퍼 내용을 읽을 수 있습니다. – sehe