2011-03-17 3 views
0

나는 서버를 boost.asio 및 PHP 클라이언트로 C++로 작성했습니다. 내가 소량의 데이터를 보내면 모든 데이터를 얻을 수 있지만 긴 문자열을 보내면 대부분 느슨해집니다. 여기 보내고받은 데이터의 크기가 같지 않음

내가 내 서버에서 데이터를 전송하는 부분입니다, 내가 65536 바이트 여기
void handle_write(const boost::system::error_code& /*error*/, 
      size_t size/*bytes_transferred*/) { 
     cout <<size<<endl; 
    } 
    void handler_read(const boost::system::error_code&, std::size_t size) { 
     istream is(&buffer); 
     string myString; 
     getline(is, myString); 

     Manager myManager(myString); 
     string response = myManager.getResponse(); 
     boost::asio::async_write(socket_, 
       boost::asio::buffer(response), 
       boost::bind(&tcp_connection::handle_write, shared_from_this(), 
         boost::asio::placeholders::error, 
         boost::asio::placeholders::bytes_transferred)); 

    } 

내가 PHP는 측면에서

string getMap(string name, string pass) { 
      if (name == "admin" && pass == "123") { 
       string response = ""; 
       ConvertTypes types; 
       response = types.intToString(MAP_HEIGHT) + " "; 
       response += types.intToString(MAP_WIDTH) + "\r\n"; 
       for (int i=0; i<MAP_HEIGHT;i++) { 
        for (int j=0;j<MAP_WIDTH;j++) { 
         response += types.intToString(
           worldMap[i][j].getHeight()) + " "; 
         response += types.intToString(
           worldMap[i][j].getIsTown()) + " "; 
         response += string (1, worldMap[i][j].getTetrain()) 
           +"\r\n"; 
        } 
       } 
       return response; 
      } else { 
       return ""; 
      } 
     } 

를 전송 될 문자열을

을 보낸 말한다 나는 보낸 데이터를 읽었고, stream_get_meta_data는 단지 8183 바이트의 데이터 만 받았습니다.

print_r($this->socket->getStatus()); 

     for ($i=0; $i<$MAP_HEIGHT;$i++) { 
      for ($j=0; $j<$MAP_WIDTH;$j++) { 

       $this->response = $this->socket->readLine(); 
       $this->response = explode(' ', $this->response); 
       echo "<p>"; 
       echo "$i $j <br>"; 
       print_r($this->response); 
       echo '<br>'; 
       print_r($keyArray); 
       $map[$i][$j] = array_combine($keyArray, $this->response); 
       $this->response = $this->socket->readLine(); 
      } } 

     } 
+0

PHP를 모르지만 네트워크 패킷이 모두 한 블록으로 전달된다는 보장이 없습니다. 잠깐 기다렸다가 다시 읽으려고하면 더 많은 정보가 있습니까? – forsvarir

답변

2

당신은 소켓을 통해 하나 개의 큰 블록을 보낼 수 있지만 수신 측 예를 들어, 작은 크기의 여러 블록을 얻을 수 있습니다 :

send -> 10000 bytes 

receive <- 3000 bytes 
receive <- 2000 bytes 
receive <- 4500 bytes 
receive <- 500 bytes 

이것은 단지 예입니다, TCP는 전송을 보장받지 않습니다 블록은 같은 크기입니다.

+0

+1 서버 측에서'send'를 한 번 호출하면 클라이언트 측에서'recv'를 한 번 호출하는 것과 같지 않습니다. 이것은 이해해야하는 중요한 개념입니다. –

0

답변을 찾았습니다. 나는 안전하지 않은 방식으로 서버에서 데이터를 보내고 있었다. async_write이 다른 것에 대한 제어를 포기했을 때 나머지 데이터는 손실되었습니다.

class shared_const_buffer { 
public: 
    // Construct from a std::string. 
    explicit shared_const_buffer(const std::string& data) 
    : data_(new std::vector<char>(data.begin(), data.end())), 
     buffer_(boost::asio::buffer(*data_)) 
    { 
    } 

    // Implement the ConstBufferSequence requirements. 
    typedef boost::asio::const_buffer value_type; 
    typedef const boost::asio::const_buffer* const_iterator; 
    const boost::asio::const_buffer* begin() const { return &buffer_; } 
    const boost::asio::const_buffer* end() const { return &buffer_ + 1; } 

private: 
    boost::shared_ptr<std::vector<char> > data_; 
    boost::asio::const_buffer buffer_; 
}; 

을하지 원시 문자열이 버퍼를 보내

는이 클래스에 문자열을 전달해야합니다. 그렇게하면 데이터가 손실되지 않습니다.

관련 문제