C++ iostream 実装資料5
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
[[C++のiostream]]
* stream 型入出力 [#k520ec67]
Stream 型入出力に対する streambuf を考える。
** 入力 [#ha1623a4]
入力は backup sequence を持たせなければ
比較的容易であると思われるが、backup sequence が無いと de...
関数が失敗する可能性がある。そこで、ここでは backup seque...
- Backup sequence の最小保持文字数を minback とする。
- 用意する buffer の先頭を表すポインタを pbgn とする。
- 用意する buffer の大きさを bufsize とする。bufsize > mi...
- pend = pbgn + busize とする。
- 初期状態では eback() = gptr() = egptr() = pbgn に設定す...
- underflow では
-- egptr - pbgn > minback の時、d = egptr() - pbgn - minb...
-- egptr() から pend までを入力列から読み込む。読み込んだ...
** 出力 [#rdf4d4b0]
出力は overflow() を上書きする。ただし、残余がある場合も...
traits::eof() 以外に指定された場合、バッファ出力後にその...
従って、この場合、完全には空にならない。
完全にバッファを出力したい場合は、
ostream で flush() を呼ぶ。ostream の flush() は省略時設...
sync() を呼ぶことになっているので、sync() を実装する。
** 実装例 [#l3305bcd]
Socket descriptor s に対する入力 stream 用の streambuf 派...
作ってみる。
この class が s に対して行う操作は recv() のみとする。
Socket descriptor の(dup() を使った)複製も行わない。
すなわち、connect()、close()、accept() など recv() 以外の...
すべてこの class の外で行うものとする。
ヘッダファイル sockbuf.h
#ifndef SOCKBUF_H_INCLUDED
#define SOCKBUF_H_INCLUDED
#include <iostream>
class Sockbuf : public std::streambuf
{
public:
Sockbuf(int s);
~Sockbuf();
protected:
virtual int sync();
virtual int underflow();
virtual int overflow(int c = std::char_traits<char>::eo...
private:
static const int minback = 256;
static const int rbufsiz = 768;
static const int wbufsiz = 512;
int m_sock;
char m_rbuf[rbufsiz];
char m_wbuf[wbufsiz];
};
#endif /* SOCKBUF_H_INCLUDED */
本体 sockbuf.cpp
#include "sockbuf.h"
#include <winsock2.h>
using namespace std;
Sockbuf::Sockbuf(int s)
{
m_sock = s;
setg(m_rbuf,m_rbuf,m_rbuf);
setp(m_wbuf,m_wbuf + wbufsiz);
}
Sockbuf::~Sockbuf()
{
}
int
Sockbuf::underflow()
{
if(egptr() > m_rbuf + minback)
{
int d = egptr() - m_rbuf - minback;
char* s = m_rbuf;
while(s < (egptr() - d))
{
*s = *(s + d);
++s;
}
setg(m_rbuf, gptr() - d, egptr() - d);
}
int m = rbufsiz - (egptr() - m_rbuf);
int n = recv(m_sock, egptr(), m, 0);
if(n <= 0)
return (int)char_traits<char>::eof();
setg(m_rbuf, gptr(), egptr() + n);
return (int)*gptr();
}
int
Sockbuf::sync()
{
if(pbase())
{
int nleft = pptr() - pbase();
char* buf = pbase();
while(nleft > 0)
{
int nsent = send(m_sock, buf, nleft, 0);
if(nsent <= 0)
return (-1);
nleft -= nsent;
buf += nsent;
}
}
setp(m_wbuf, m_wbuf + wbufsiz);
return 0;
}
int
Sockbuf::overflow(int c)
{
if(pbase())
{
int d = pptr() - pbase();
if(d > 0)
{
int n = send(m_sock, pbase(), d, 0);
if(n <= 0)
return (int)char_traits<char>::eof();
char* s = pbase();
while((s + n) < pptr())
{
*s = *(s + n);
++s;
}
pbump(-n);
}
else
setp(m_wbuf, m_wbuf + wbufsiz);
if(c != char_traits<char>::eof())
{
*pptr() = (char)c;
pbump(1);
return c;
}
return (int)char_traits<char>::not_eof(c);
}
return (int)char_traits<char>::eof();
}
* 使用例 [#i3165fcf]
[[TCP接続用 C library]] と組み合わせた例を示す。Source fi...
exam.cpp とする時、Windows の場合
gcc -c -DWIN32 tcplib.c
g++ -DWIN32 exam.cpp sockbuf.cpp tcplib.o -lws2_32 -oexa...
** 使用例1[#n4712caa]
サーバに接続して、文字を読み出し表示する。切断はサーバ側...
#include "sockbuf.h"
#include "tcplib.h"
using namespace std;
int main(int argc, char* argv[])
{
int port;
SOCKET s;
if(argc != 3)
{
cerr << "Usage " << argv[0] << " host port" << endl;
return (-1);
}
port = atoi(argv[2]);
netlibstart();
s = tcpsocket();
tcpopen(s, argv[1], port);
Sockbuf mybuf(s);
std::istream mystream(&mybuf);
char c;
while(mystream.get(c))
cout << c;
tcpclose(s);
netlibstop();
return 0;
}
** 使用例2 [#j4bc1283]
Http クライアントもどき。Host port を指定すると、そのルー...
要求し、応答を表示する。
#include "sockbuf.h"
#include "tcplib.h"
using namespace std;
int main(int argc, char* argv[])
{
int port;
SOCKET s;
if(argc != 3)
{
cerr << "Usage: " << argv[0] << " host port" << endl;
return (-1);
}
port = atoi(argv[2]);
netlibstart();
s = tcpsocket();
tcpopen(s, argv[1], port);
Sockbuf mybuf(s);
std::iostream mystream(&mybuf);
mystream << "GET / HTTP/1.0";
mystream.put(0x0d); // CR
mystream.put(0x0a); // LF
mystream.put(0x0d); // CR
mystream.put(0x0a); // LF
mystream.flush();
char c;
while(mystream.get(c))
cout << c;
tcpclose(s);
netlibstop();
return 0;
}
終了行:
[[C++のiostream]]
* stream 型入出力 [#k520ec67]
Stream 型入出力に対する streambuf を考える。
** 入力 [#ha1623a4]
入力は backup sequence を持たせなければ
比較的容易であると思われるが、backup sequence が無いと de...
関数が失敗する可能性がある。そこで、ここでは backup seque...
- Backup sequence の最小保持文字数を minback とする。
- 用意する buffer の先頭を表すポインタを pbgn とする。
- 用意する buffer の大きさを bufsize とする。bufsize > mi...
- pend = pbgn + busize とする。
- 初期状態では eback() = gptr() = egptr() = pbgn に設定す...
- underflow では
-- egptr - pbgn > minback の時、d = egptr() - pbgn - minb...
-- egptr() から pend までを入力列から読み込む。読み込んだ...
** 出力 [#rdf4d4b0]
出力は overflow() を上書きする。ただし、残余がある場合も...
traits::eof() 以外に指定された場合、バッファ出力後にその...
従って、この場合、完全には空にならない。
完全にバッファを出力したい場合は、
ostream で flush() を呼ぶ。ostream の flush() は省略時設...
sync() を呼ぶことになっているので、sync() を実装する。
** 実装例 [#l3305bcd]
Socket descriptor s に対する入力 stream 用の streambuf 派...
作ってみる。
この class が s に対して行う操作は recv() のみとする。
Socket descriptor の(dup() を使った)複製も行わない。
すなわち、connect()、close()、accept() など recv() 以外の...
すべてこの class の外で行うものとする。
ヘッダファイル sockbuf.h
#ifndef SOCKBUF_H_INCLUDED
#define SOCKBUF_H_INCLUDED
#include <iostream>
class Sockbuf : public std::streambuf
{
public:
Sockbuf(int s);
~Sockbuf();
protected:
virtual int sync();
virtual int underflow();
virtual int overflow(int c = std::char_traits<char>::eo...
private:
static const int minback = 256;
static const int rbufsiz = 768;
static const int wbufsiz = 512;
int m_sock;
char m_rbuf[rbufsiz];
char m_wbuf[wbufsiz];
};
#endif /* SOCKBUF_H_INCLUDED */
本体 sockbuf.cpp
#include "sockbuf.h"
#include <winsock2.h>
using namespace std;
Sockbuf::Sockbuf(int s)
{
m_sock = s;
setg(m_rbuf,m_rbuf,m_rbuf);
setp(m_wbuf,m_wbuf + wbufsiz);
}
Sockbuf::~Sockbuf()
{
}
int
Sockbuf::underflow()
{
if(egptr() > m_rbuf + minback)
{
int d = egptr() - m_rbuf - minback;
char* s = m_rbuf;
while(s < (egptr() - d))
{
*s = *(s + d);
++s;
}
setg(m_rbuf, gptr() - d, egptr() - d);
}
int m = rbufsiz - (egptr() - m_rbuf);
int n = recv(m_sock, egptr(), m, 0);
if(n <= 0)
return (int)char_traits<char>::eof();
setg(m_rbuf, gptr(), egptr() + n);
return (int)*gptr();
}
int
Sockbuf::sync()
{
if(pbase())
{
int nleft = pptr() - pbase();
char* buf = pbase();
while(nleft > 0)
{
int nsent = send(m_sock, buf, nleft, 0);
if(nsent <= 0)
return (-1);
nleft -= nsent;
buf += nsent;
}
}
setp(m_wbuf, m_wbuf + wbufsiz);
return 0;
}
int
Sockbuf::overflow(int c)
{
if(pbase())
{
int d = pptr() - pbase();
if(d > 0)
{
int n = send(m_sock, pbase(), d, 0);
if(n <= 0)
return (int)char_traits<char>::eof();
char* s = pbase();
while((s + n) < pptr())
{
*s = *(s + n);
++s;
}
pbump(-n);
}
else
setp(m_wbuf, m_wbuf + wbufsiz);
if(c != char_traits<char>::eof())
{
*pptr() = (char)c;
pbump(1);
return c;
}
return (int)char_traits<char>::not_eof(c);
}
return (int)char_traits<char>::eof();
}
* 使用例 [#i3165fcf]
[[TCP接続用 C library]] と組み合わせた例を示す。Source fi...
exam.cpp とする時、Windows の場合
gcc -c -DWIN32 tcplib.c
g++ -DWIN32 exam.cpp sockbuf.cpp tcplib.o -lws2_32 -oexa...
** 使用例1[#n4712caa]
サーバに接続して、文字を読み出し表示する。切断はサーバ側...
#include "sockbuf.h"
#include "tcplib.h"
using namespace std;
int main(int argc, char* argv[])
{
int port;
SOCKET s;
if(argc != 3)
{
cerr << "Usage " << argv[0] << " host port" << endl;
return (-1);
}
port = atoi(argv[2]);
netlibstart();
s = tcpsocket();
tcpopen(s, argv[1], port);
Sockbuf mybuf(s);
std::istream mystream(&mybuf);
char c;
while(mystream.get(c))
cout << c;
tcpclose(s);
netlibstop();
return 0;
}
** 使用例2 [#j4bc1283]
Http クライアントもどき。Host port を指定すると、そのルー...
要求し、応答を表示する。
#include "sockbuf.h"
#include "tcplib.h"
using namespace std;
int main(int argc, char* argv[])
{
int port;
SOCKET s;
if(argc != 3)
{
cerr << "Usage: " << argv[0] << " host port" << endl;
return (-1);
}
port = atoi(argv[2]);
netlibstart();
s = tcpsocket();
tcpopen(s, argv[1], port);
Sockbuf mybuf(s);
std::iostream mystream(&mybuf);
mystream << "GET / HTTP/1.0";
mystream.put(0x0d); // CR
mystream.put(0x0a); // LF
mystream.put(0x0d); // CR
mystream.put(0x0a); // LF
mystream.flush();
char c;
while(mystream.get(c))
cout << c;
tcpclose(s);
netlibstop();
return 0;
}
ページ名: