2010-11-29 12 views
0

文字が\ n文字に達するまでそれぞれの文字を読んで、それらを一緒に結合して返しますか、より良い方法がありますか?私はこのためにstd :: stringまたはcharを使うべきですか? ソケットから読み込んで個々の行を返すにはどうしたらいいですか?

は、私は次の2つの例を試してみましたが、私は1

例別の行として、それらを読んでする必要があります。

std::string sockread() 
{ 
    std::string s; 
    s.resize(DEFAULT_BUFLEN); 
    int result = recv(m_socket, &s[0], DEFAULT_BUFLEN, 0); 

    if (result > 0) { 
     return s; 
    } else if (result == 0) { 
     connected = false; 
    } else { 
     std::cout << "recv failed with error " << WSAGetLastError() << "\n"; 
    } 
    throw std::runtime_error("Socket connection failed!"); 
} 

例2:

char sockread(void) 

    { 
    int result; 
    char buffer[DEFAULT_BUFLEN]; 
     result = recv(m_socket, buffer, DEFAULT_BUFLEN, 0); 

     if (result > 0) { 
      return *buffer; 
       } 
      else if (result == 0) 
       { 
      connected = false; 
       return *buffer; 
       } 
      else { 
     printf("recv failed with error: %d\n", WSAGetLastError()); 
     return *buffer; 
     } 

    } 

答えて

0

あなたが持っています残りのソケットコードの配置方法に応じていくつかのオプションがあります。

最も簡単なアプローチは、コーディングの観点から、探している文字に出会うまで一度に1文字ずつ読み込むことです。あなたは、少なくともメモリの断片化を避けるためにローカルバッファを使用することができますが、これは例えば、パフォーマンスの観点から最善のアプローチではありません。一方

std::string sockread(void) 
{ 
    char buffer[DEFAULT_BUFLEN]; 
    int buflen = 0; 
    char c; 
    std::string s; 

    do 
    { 
     int result = recv(m_socket, &c, 1, 0); 
     if (result > 0) 
     { 
      if (c == '\n') 
       break; 

      if (buflen == DEFAULT_BUFLEN) 
      { 
       s += std::string(buffer, buflen); 
       buflen = 0; 
      } 

      buffer[buflen] = c; 
      ++buflen; 

      continue; 
     } 

     if (result == SOCKET_ERROR) 
     { 
      if (WSAGetLastError() == WSAEWOULDBLOCK) 
       continue; 

      std::cout << "recv failed with error " << WSAGetLastError() << "\n"; 
     } 
     else 
      connected = false; 

     throw std::runtime_error("Socket connection failed!"); 
    } 
    while (true); 

    if (buflen > 0) 
     s += std::string(buffer, buflen); 

    return s; 
} 

、中間バッファに生のソケットデータの読み込みデータが迅速に(反対側にあまりブロッキングを引き起こす)ソケットのバッファの外に得ているので、必要に応じてあなたの読書機能へのアクセスの残りの部分がソケットのより効率的な読み取りを可能にすること、例えば:

std::vector<unsigned char> buffer; 

std::string sockread(void) 
{ 
    unsigned char buf[DEFAULT_BUFLEN]; 
    int result; 
    std:vector<unsigned char>::iterator it; 

    do 
    { 
     it = std::find(buffer.begin(), buffer.end(), '\n'); 
     if (it != buffer.end()) 
      break; 

     result = recv(m_socket, buf, DEFAULT_BUFLEN, 0); 
     if (result > 0) 
     { 
      std::vector<unsigned char>::size_type pos = buffer.size(); 
      buffer.resize(pos + result); 
      memcpy(&buffer[pos], buf, result); 
      continue; 
     } 

     if (result == SOCKET_ERROR) 
     { 
      if (WSAGetLastError() == WSAEWOULDBLOCK) 
       continue; 

      std::cout << "recv failed with error " << WSAGetLastError() << "\n"; 
     } 
     else 
      connected = false; 

     throw std::runtime_error("Socket connection failed!"); 
    } 
    while (true); 

    std::string s((char*)&buffer[0], std::distance(buffer.begin(), it)); 
    buffer.erase(buffer.begin(), it); 
    return s; 
} 
+0

第二の方法を使用して、私はこのエラーを取得しています - エラーC2664:「RECV」:からパラメータ2を変換することはできません「unsigned char型[512]」 タイプが指さ「のchar *」には無関係です。変換はreinterpret_cast、Cスタイルのキャストまたはファンクションスタイルのキャスト – thorvald

+0

を必要とし、buf [DEFAULT_BUFLEN]に変更すると(悪いかどうかわからない場合)、最初の行だけが返され、残りは空の文字列になります。 – thorvald

+0

エラーメッセージのように、タイプキャストを使用してください: 'result = recv(m_socket、(char *)buf、DEFAULT_BUFLEN、0); ' –

0

利用ブースト.ASIO - ラインベースの操作はhereをカバーしました。

多くの一般的に使用されるインターネット・プロトコル はラインベース、彼らは文字列 「\ rを\ n」はで を区切られているプロトコル要素を持っている ことを意味しています。たとえば、HTTP、SMTP 、FTPなどがあります。 Boost.Asio には、read_until() とasync_read_until()関数が含まれています。

+0

提案をありがとう。私もそれを試してみましょう。 – thorvald

+0

ライブラリーのコードが安定しているので、ライブラリーのグリップを取得するにはもう少し作業が必要ですが、一度起動すると作業が少なくなります。 –

関連する問題