iostream と streambuf

前頁の考察から、TCP connection に対し iostream 化する ことを考える。とりあえず buffer pointer を渡さずに

int underflow();
int uflow();
int overflow(int c=std::char_traits<char>::eof());
int sync();

だけを実装してみた。

host, port が与えられたとして

try
{
  char linebuf[1024];
  SocketLibrary netlib;
  InternetAddress addr(host,port);
  TcpBuffer tcp(PF_INET, SOCK_STREAM);
  std::iostream strm((std::streambuf*)&tcp);

  if(tcp.connect(addr.socketaddress(), addr.addresslength())
      != Socket::sockerr)
  {
    std::streamsize n;
    std::cout << "Connected" << std::endl;
    strm << "GET / HTTP/1.0";
    strm.put(0x0d);
    strm.put(0x0a);
    strm.put(0x0d);
    strm.put(0x0a);
    strm.flush();
    while(strm.getline(linebuf,1023))
    {
      n = strm.gcount();
      linebuf[n] = 0;
      std::cout << linebuf << std::endl;
    }
    n = strm.gcount();
    if( n )
    {
      linebuf[n] = 0;
      std::cout << linebuf << std::endl;
    }
    tcp.close();
  }
  else
  {
    std::cout << "Connection fail" << std::endl;
  }
}
catch(...)
{
   :
}

という使い方で動いた。CR(0x0d)/LF(0x0a) を endl() で 出せるようにするには、fstream の binary mode の not の 場合を見ればよいのかも知れない。

一応 putnl() という(CR/LF を置くだけで flush しない) マニピュレータ関数を用意してみた。iostream では write が 認識されないみたいで、とりあえず ostream と istream を 別々にして

std::ostream& putnl(std::ostream& s)
{
  static const char crlf[2] = { 0x0d, 0x0a };
  return s.write(crlf, 2);
}

try
{
  char linebuf[1024];
  SocketLibrary netlib;
  InternetAddress addr(host,port);
  TcpBuffer tcp(PF_INET, SOCK_STREAM);
  std::ostream ostrm((std::streambuf*)&tcp);
  std::istream istrm((std::streambuf*)&tcp);

  if(tcp.connect(addr.socketaddress(), addr.addresslength())
      != Socket::sockerr)
  {
    std::streamsize n;
    std::cout << "Connected" << std::endl;
    ostrm << "GET / HTTP/1.0" << putnl << putnl <<std::flush;
    while(istrm.getline(linebuf,1023))
    {
      n = istrm.gcount();
      linebuf[n] = 0;
      std::cout << linebuf << std::endl;
    }
    n = istrm.gcount();
    if( n )
    {
      linebuf[n] = 0;
      std::cout << linebuf << std::endl;
    }
    tcp.close();
  }
  else
  {
    std::cout << "Connection fail" << std::endl;
  }
}
catch(...)
{
   :
}

よく考えてみると、iostream は istream と ostream から派生しているので、 わざわざ分ける必要はない。try ブロックの中だけ示すと、

try
{
  char linebuf[1024];
  SocketLibrary netlib;
  InternetAddress addr(host,port);
  TcpBuffer tcp(PF_INET, SOCK_STREAM);
  std::iostream strm((std::streambuf*)&tcp);

  if(tcp.connect(addr.socketaddress(), addr.addresslength())
      != Socket::sockerr)
  {
    std::streamsize n;
    std::cout << "Connected" << std::endl;
    strm << "GET / HTTP/1.0" << putnl << putnl <<std::flush;
    while(strm.getline(linebuf,1023))
    {
      n = strm.gcount();
      linebuf[n] = 0;
      std::cout << linebuf << std::endl;
    }
    n = strm.gcount();
    if( n )
    {
      linebuf[n] = 0;
      std::cout << linebuf << std::endl;
    }
    tcp.close();
  }
  else
  {
    std::cout << "Connection fail" << std::endl;
  }
}

でよい。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2006-05-19 (金) 13:18:20