2012-05-23 78 views
1

首先,我想說的是,我是一名C++初學者,總體來說,儘管我對Java和C#等語言有一定的經驗。增強套接字問題

這就是說,我通過Boost TCP套接字傳輸數據時遇到問題。我使用此代碼:

派:

tcp::socket s(io_service); 
     boost::asio::connect(s, iterator); 
     string response = static_cast<ostringstream*>(&(ostringstream() << arg1))->str() 
      + "," + static_cast<ostringstream*>(&(ostringstream() << arg2))->str() 
      + "," + static_cast<ostringstream*>(&(ostringstream() << arg3))->str() 
      + "," + static_cast<ostringstream*>(&(ostringstream() << arg4))->str() 
      + "," + static_cast<ostringstream*>(&(ostringstream() << arg5))->str() 
      + "," + static_cast<ostringstream*>(&(ostringstream() << arg6))->str(); 

     //pad the rest 
     while (response.length() < max_length) 
     { 
      response += ' '; 
     } 
     boost::asio::write(s, boost::asio::buffer(response, sizeof(response))); 

爲:

tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port)); 
    while(true) 
    { 
     socket_ptr sock(new tcp::socket(io_service)); 
     a.accept(*sock); 
     boost::thread t(boost::bind(session, sock)); 
    } 
... 
void session(socket_ptr sock) 
{ 
    char data[max_length]; 
    size_t length; 
    try 
    { 
     while(true) 
     {   
      boost::system::error_code error; 
      //size_t length = sock->read_some(boost::asio::buffer(data), error); 
      length = boost::asio::read(*sock, boost::asio::buffer(data, sizeof data)); 
      std::cout << "Length " << length << endl; 
      if (error == boost::asio::error::eof) 
      { 
       break; // Connection closed cleanly by peer. 
      } 
      else if (error) 
      { 
       throw boost::system::system_error(error); // Some other error. 
      } 

     } 
    } 
    catch (std::exception& e) 
    { 
     std::cout << data << endl; 
     string message = e.what(); 
     if(std::string::npos != message.find(END_OF_FILE)) 
     { 
      domeSomethingWithTheData(data); 
      memset(data, 0, sizeof data); 
     } 
     else 
     { 
      std::cout << data <<endl; 
      std::cerr << "Exception in thread: " << e.what() << "\n"; 
     } 
    } 
} 

我無法理解的是,無論我用,(無論是boost::asio::readsock->read_some)我從來沒有得到超過32個字符的數據。我曾嘗試將緩衝區的大小增加到2048,但問題依然存在。

緩衝區總是包含超過32個字符(其中大部分是垃圾),但我假設這些實際上並不是從客戶端發送的,而是來自服務器端的緩衝區的實際分配,因爲std::cout << "Length " << length打印out 32.

有關我如何從客戶端發送任意數量的字符到服務器的任何信息,我們將不勝感激。

編輯:

由拉法爾Rawicki提供的三分球之後,我現在使用此代碼:

boost::asio::streambuf buffer; 
    boost::asio::read_until(*sock, buffer, '\n'); 
    std::istream is(&buffer); 
    std::string line; 
    std::getline(is, line); 
    std::cout << line << std::endl; 

的客戶端仍然與我在結尾處增加一個\n唯一的例外不變。但是,這會產生很多End of file異常。

回答

2

boost::asio::read你用過的應該讀取數據,直到緩衝區已滿或發生錯誤。

boost::asio::socket::read_some應該從套接字讀取一些數據

讀取數據的所需金額,您可以:

  • 使用boost :: ASIO ::閱讀你嘗試過。
  • 使用這些函數的多個調用來讀取數據越來越多
  • 使用read_until到數據讀出到預期定界符
  • 使用本boost::asio::read過載,這需要作爲參數completion_condition,例如,字節數。

此外,請使用Boost.Asio查看issues with synchronous operations,並考慮使用異步操作。

編輯:我錯過了錯誤的客戶端代碼中的緩衝區初始化。使用boost::asio::read是正確的。

你不能這樣初始化緩衝區:

boost::asio::buffer(response, sizeof(response)); 

因爲sizeof回報std::string結構的大小,而不是整個字符串。在我的機器上它總是8.使用:

boost::asio::buffer(response); 
+0

感謝您的指針。我已經讀過'read_some'不能保證返回所有的數據,但是我不知道'read'也適用。我現在試圖使用'read_until'。問題是,它似乎工作,但是,我收到了很多'文件結束'異常。你有什麼想法我可以通過這個嗎?我將更新我現在正在使用的代碼。 – npinti

+0

@npinti我已經在Boost文檔中的適當重載的答案中鏈接了兩個讀取 - 它僅適用於'read'的特定重載。 –

+0

@npinti'boost :: asio :: buffer(response,sizeof(response)));' - 這行是完全錯誤的,** use:'boost :: asio :: buffer(response);'**。 Sizeof不返回字符串的有效大小。 'boost :: asio :: buffer'有一個字符串重載,如果你想這樣做,它應該是'boost :: asio :: buffer(response.c_str(),response.size())) ;' –

3

這實際上不是你的問題的答案。但簡短的建議。

你的字符串連接代碼是殘酷的!

string response = static_cast<ostringstream*>(&(ostringstream() << arg1))->str() 
     + "," + static_cast<ostringstream*>(&(ostringstream() << arg2))->str() 
     + "," + static_cast<ostringstream*>(&(ostringstream() << arg3))->str() 
     + "," + static_cast<ostringstream*>(&(ostringstream() << arg4))->str() 
     + "," + static_cast<ostringstream*>(&(ostringstream() << arg5))->str() 
     + "," + static_cast<ostringstream*>(&(ostringstream() << arg6))->str(); 

對於每個精氨酸您創建一個新ostringstream,值寫它,那麼你不必要取消對它的引用,那麼你不必要丟給它已經擁有反正類型。最後你使用字符串連接來建立你的最終字符串。

這種字符串連接既不高效也不復雜(需要臨時對象,一些浪費的分配等)。

ostringstream是字符串連接和格式化的正確工具,它是高效和複雜的。

長話短說,你的代碼,而應該是這樣的:

ostringstream oss; 
oss << arg1 << "," << arg2 << "," << arg3 << "," << arg4 << "," << arg5 << "," << arg6; 
string response = oss.str(); 
+0

感謝您的提示,非常感謝。 – npinti