0

먼저 환경 데이터를 푼다 버전의 부족한 부분을 무시하고 시간 초과는 무시하십시오!)간단한 클라이언트/서버 전송에 라인 (부스트/윈도우)

서버가 클라이언트가 "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 ; 
     } 
} 
+0

KK

이없는 최고의 버전, 대신 클라이언트의 현재 코드의입니다. 나는 답을 알아. 'readln()'에서는 버퍼 된 클래스 (istream)를 사용하여 한 줄 이상을 먹지만, 모든 데이터를 소비하지는 않습니다. – Grzegorz

+0

받은 모든 데이터를 소비하고 있으며, 사용자가 처리하는 'streambuf'에 의해 "소비"됩니다. 'streambuf'를 활성 상태로 유지하면 다음에 사용할 버퍼 내용을 읽을 수 있습니다. – sehe

답변

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" ; 
    }