1

これが私が取り組んでいる単純なエコーサーバーです。サーバーはクライアントからの要求を受け入れ、クライアントが送信したものを返します。プログラムは で正常に動作しますがsocat、自分のクライアントを使用するとフリーズします。

私の古いコードの問題は、read代わりにread_some. read特定のバイト数を読み取るか、壊れたパイプ例外が発生するまでパイプをブロックしますがread_some、一度にチャンクを読み取ります。更新されたバージョンはread_some、入力ストリームを読み取り、プログラムが読み取った最後の文字が であるかどうかを確認するために\0使用し\0ます。これは、文字列リテラルのみを渡し、パイプにバイナリ データがないため機能します。

サーバーのコードは

using namespace std;

const char* epStr = "/tmp/socketDemo";

int main() {
  namespace local = boost::asio::local;

  boost::asio::io_service io_service;

  ::unlink(epStr);

  local::stream_protocol::endpoint ep(epStr);
  local::stream_protocol::acceptor acceptor(io_service, ep);

  while(1) {
    local::stream_protocol::socket *socket = new local::stream_protocol::socket(io_service);
    acceptor.accept(*socket);

    char buf[2048] = {0};
    boost::system::error_code error;

    size_t len = 0;
      while(1) {
        len += socket->read_some(boost::asio::buffer(buf + len, 2048 - len));
        cout << "read " << len << endl;
        if (buf[len] == '\0') {
          break;
        }
      }

    cout << "read " << len << " bytes" << endl;
    cout << buf << endl;

    boost::asio::write(*socket, boost::asio::buffer(buf, len), boost::asio::transfer_all());
  }
}

socatたとえば、コマンドを使用してサーバーをテストする場合

echo "12345" | socat - UNIX-CONNECT:/tmp/socketDemo

目的の結果が返されます。

私のクライアントコードは

const char* epStr = "/tmp/socketDemo";

int main(int argc, const char* argv[]) {
  boost::asio::io_service io_service;
  boost::asio::local::stream_protocol::endpoint ep(epStr);
  boost::asio::local::stream_protocol::socket socket(io_service);

  socket.connect(ep);

  boost::asio::write(socket, boost::asio::buffer(argv[1], strlen(argv[1])), boost::asio::transfer_all());

  char buf[1024] = {0};

  size_t len = 0;
    while(1) {
      len += socket.read_some(boost::asio::buffer(buf + len, 2048 - len));
      std::cout << "read " << len << std::endl;
      if (buf[len] == '\0') {
        break;
      }
    }

  std::cout << "read " << len << " bytes\n";

  std::cout << buf << std::endl;

  socket.close();

クライアントを実行すると、最初はどちらも出力がありません。クライアントを強制終了した後、サーバーは n バイトを読み取り、壊れたパイプ例外を取得することを出力します。

readこれはサーバーの機能が原因でしょうか? もしそうなら、各メッセージの最初にデータチャンクのサイズを送信せずに、どれだけのデータを読み取る必要があるかを知らせる方法はありますか? また、なぜsocatこのサーバーで問題なく動作できるのだろうかと思っています。ありがとう!

4

1 に答える 1

1

また、なぜ socat がこのサーバーで問題なく動作するのか疑問に思っています。

おそらく socat がソケットを閉じ、クライアントが閉じないためです。

もしそうなら、各メッセージの最初にデータチャンクのサイズを送信せずに、どれだけのデータを読み取る必要があるかを知らせる方法はありますか?

たとえば、EOM を含むプロトコルを定義/使用していると仮定して、メッセージの終わりの文字を読み取るまで一度に 1 バイトずつ読み取ります。

于 2016-01-04T21:37:42.257 に答える