C++ iostream 実装例 その 7
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
[[C++のiostream]]
* C++ iostream 実装例 その 7 [#dde2b5e9]
前節([[C++ iostream 実装例 その 6]])で、必要な機能は全部...
押し込めた。ここまでくれば、iostream 化は容易である。
まず名前であるが、tcpstream としてもよいのだが、tcpclient...
TCP の stream には他にも、例えば accept が返す socket に...
が考えられるからである。
fstream に習って、constructor は
- tcpclient();
- tcpclient(const char* host, int port);
の二つ。いずれも例外を throw することはない。
独自に実装する member 関数も fstream に習って
- tcpclient* rdbuf() const;
- void connect(const char* host, int port);
- void close();
- bool is_connect() const;
の4つとする。
** 修正 2010-01-13 [#j40cbd5d]
- sync() の return の前に setp() による位置調整が必要。加...
** 概要 [#u861df0a]
基本的には、tcpclient は tcpbuffer を member 変数として保...
tcpclient に独自に実装する関数は、tcpbuffer の関数を呼び...
だけである。この時、connect() 及び close() はその結果によ...
failbit を設定する。
connect() まで行う constructor にあっても同様である。
この bit を設定すると、基底 class の iostream で exceptio...
判定して、exception を throw するかどうかを決めるので、派...
実装する必要は無い。
** header file [#q0c4d474]
この class のための include file を別に作ってもよいのだが、
tcpbuffer とは切っても切れない関係なので、
前の mytcpbuf.h に追加する形にして、ここでは mytcplib.h ...
一つの file にまとめる。
// mytcplib.h
#ifndef MY_TCPLIBRARY_H_INCLUDED
#define MY_TCPLIBRARY_H_INCLUDED
#ifdef WINSOCK
#include <winsock2.h>
#include <ws2tcpip.h>
#endif // WINSOCK
#include <streambuf>
#include <iostream>
namespace mynetlibrary
{
#ifndef WINSOCK
typedef int SOCKET;
#endif // WINSOCK
class netlibrary
{
public:
netlibrary(void);
~netlibrary(void);
private:
static bool m_libloaded;
};
class tcpbuffer :
public std::streambuf
{
public:
tcpbuffer(void);
virtual ~tcpbuffer(void);
bool is_connect(void) const;
int connect(const char* host, int port);
int close(void);
protected:
virtual int underflow(void);
virtual int overflow(int c = std::char_traits<char>::eo...
virtual int sync(void);
private:
tcpbuffer(const tcpbuffer& src);
tcpbuffer& operator=(const tcpbuffer& src);
protected:
#ifndef WINSOCK
static const int INVALID_SOCKET = (-1);
#endif // WINSOCK
static const int MY_MAXGBACK = 128;
static const int MY_GBUFSIZE = 1024;
static const int MY_PBUFSIZE = 1024;
protected:
SOCKET m_socket;
char* m_gbuf;
char m_rbuf[(MY_MAXGBACK + MY_GBUFSIZE + 1)];
char m_pbuf[(MY_PBUFSIZE + 1)];
};
class tcpclient :
public std::iostream
{
public:
tcpclient(void);
tcpclient(const char* host, int port);
tcpbuffer* rdbuf(void) const;
void connect(const char* host, int port);
void close(void);
bool is_connect(void) const;
private:
tcpclient(const tcpclient& src);
tcpclient& operator=(const tcpclient& src);
protected:
tcpbuffer m_tcpbuf;
};
} // namespace mynetlibrary
#endif // MY_TCPLIBRARY_H_INCLUDED
** source file [#la17886e]
定義の方は、簡単である。
// mytcpcli.cpp
#include "mytcplib.h"
namespace mynetlibrary
{
tcpclient::tcpclient(void) :
std::iostream(0)
{
this->init(&m_tcpbuf);
}
tcpclient::tcpclient(const char* host, int port) :
std::iostream(0)
{
this->init(&m_tcpbuf);
if(m_tcpbuf.connect(host, port) != 0)
this->setstate(std::ios::failbit);
else
this->clear();
}
tcpbuffer*
tcpclient::rdbuf(void) const
{
return const_cast<tcpbuffer*>(&m_tcpbuf);
}
void
tcpclient::connect(const char* host, int port)
{
if(m_tcpbuf.connect(host, port) != 0)
this->setstate(std::ios::failbit);
else
this->clear();
}
void
tcpclient::close(void)
{
if(m_tcpbuf.close() != 0)
this->setstate(std::ios::failbit);
else
this->clear();
}
bool
tcpclient::is_connect(void) const
{
return m_tcpbuf.is_connect();
}
} // namespace mynetlibrary
** sample programs [#ucc46599]
前の sample も書き換えてみよう。
// testbuf3.cpp
#include "mytcplib.h"
char linebuf[4096];
int
main(int argc, char* argv[])
{
mynetlibrary::netlibrary lib;
if(argc != 2)
{
std::cerr << "Usage: " << argv[0] << " host" << std::e...
return (-1);
}
mynetlibrary::tcpclient tcpstream(argv[1], 80);
tcpstream << "GET / HTTP/1.0\r\n";
tcpstream << "Host: " << argv[1] << "\r\n";
tcpstream << "\r\n";
tcpstream.flush();
while(tcpstream.getline(linebuf, 4095))
{
std::streamsize n = tcpstream.gcount();
linebuf[n] = 0;
std::cout << linebuf << std::endl;
}
std::cout.flush();
return 0;
}
前に fstream でやった try-catch の例も、全く対称に書ける。
// testbuf4.cpp
#include "mytcplib.h"
char linebuf[4096];
int
main(int argc, char* argv[])
{
mynetlibrary::netlibrary lib;
if(argc != 2)
{
std::cerr << "Usage: " << argv[0] << " host" << std::e...
return (-1);
}
mynetlibrary::tcpclient tcpstream;
tcpstream.exceptions(mynetlibrary::tcpclient::badbit | ...
try
{
tcpstream.connect(argv[1],80);
tcpstream << "GET / HTTP/1.0\r\n";
tcpstream << "Host: " << argv[1] << "\r\n";
tcpstream << "\r\n";
tcpstream.flush();
while(tcpstream.getline(linebuf, 4095))
{
std::streamsize n = tcpstream.gcount();
linebuf[n] = 0;
std::cout << linebuf << std::endl;
}
std::cout.flush();
}
catch(mynetlibrary::tcpclient::failure& e)
{
std::cerr << "Failure: " << e.what() << std::endl;
}
return 0;
}
** 補足 [#d339ae34]
mytcpbuf.cpp の方も(本質的ではないが)若干書き換えたので...
// mytcpbuf.cpp
#ifndef WINSOCK
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif // WINSOCK
#include "mytcplib.h"
namespace mynetlibrary
{
bool
netlibrary::m_libloaded = false;
netlibrary::netlibrary(void)
{
if(m_libloaded)
return;
#ifdef WINSOCK
WORD wVersion;
WSADATA wsaData;
wVersion = MAKEWORD(2,2);
if(::WSAStartup( wVersion, &wsaData ))
m_libloaded = false;
else
m_libloaded = true;
#else // WINSOCK
m_libloaded = true;
#endif // WINSOCK
}
netlibrary::~netlibrary(void)
{
if(!m_libloaded)
return;
#ifdef WINSOCK
::WSACleanup();
#endif // WINSOCK
m_libloaded = false;
}
tcpbuffer::tcpbuffer(void)
{
m_socket = INVALID_SOCKET;
m_gbuf = m_rbuf + MY_MAXGBACK;
this->setg((char*)m_gbuf, (char*)m_gbuf, (char*)m_gbuf);
this->setp((char*)m_pbuf, (char*)(m_pbuf + MY_PBUFSIZE));
}
tcpbuffer::~tcpbuffer(void)
{
this->close();
}
bool
tcpbuffer::is_connect(void) const
{
if(m_socket == INVALID_SOCKET)
return false;
return true;
}
int
tcpbuffer::connect(const char* host, int port)
{
// Returns 0 if success, otherwise returns non-zero.
if(m_socket != INVALID_SOCKET)
return (-1); // already conected
m_socket = ::socket(PF_INET, SOCK_STREAM, 0);
if(m_socket == INVALID_SOCKET)
return (-2);
#ifndef USE_GETHOSTBYNAME
struct sockaddr_in srvaddr;
struct sockaddr_in* resaddr;
struct addrinfo hints;
struct addrinfo* restop;
struct addrinfo* res;
int err;
res = 0;
::memset((char*)&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if((err = ::getaddrinfo(host, 0, &hints, &restop)) != 0)
{
this->close();
return (-3);
}
res = restop;
while(res)
{
resaddr = (struct sockaddr_in*)res->ai_addr;
::memset((char*)&srvaddr, 0, sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = ::htons((u_short)port);
srvaddr.sin_addr = resaddr->sin_addr;
if(::connect(m_socket, (struct sockaddr*)&srvaddr, siz...
break;
res = res->ai_next;
}
::freeaddrinfo(restop);
if(!res)
{
this->close();
return (-4);
}
#else // USE_GETHOSTBYNAME
struct sockaddr_in srvaddr;
unsigned long inaddr;
struct hostent *hp;
::memset((char*)&srvaddr, 0, sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = ::htons((u_short)port);
if((inaddr = ::inet_addr(host)) != INADDR_NONE)
{
::memcpy((char*)&srvaddr.sin_addr, (char*)&inaddr, siz...
if(::connect(m_socket, (struct sockaddr*)&srvaddr, siz...
{
this->close();
return (-3);
}
}
else
{
if((hp = ::gethostbyname(host)) == 0)
{
this->close();
return (-4);
}
if(hp->h_addrtype != AF_INET)
{
this->close();
return (-5);
}
const char** addr = (const char**)hp->h_addr_list;
while(*addr)
{
::memcpy((char*)&srvaddr.sin_addr, (char*)(*addr), hp...
if(::connect(m_socket, (struct sockaddr*)&srvaddr, si...
break;
++addr;
}
if(*addr == 0)
{
this->close();
return (-6);
}
}
#endif // USE_GETHOSTBYNAME
return 0;
}
int
tcpbuffer::close(void)
{
if(m_socket == INVALID_SOCKET)
return -1;
int ret;
#ifndef WINSOCK
ret = ::close(m_socket);
#else // WINSOCK
ret = ::closesocket(m_socket);
#endif // WINSOCK
m_socket = INVALID_SOCKET;
return ret;
}
int
tcpbuffer::underflow(void)
{
if(m_socket == INVALID_SOCKET)
return std::char_traits<char>::eof();
int c;
if((gptr() >= (char*)m_gbuf) && (gptr() < egptr()))
{
// Why call me ?
// Still we have enough data in the buffer.
c = (int)*gptr(); c &= 255;
return c;
}
// Move the previos (tail) data in backup area.
int nback = (int)(egptr() - eback());
if(nback > MY_MAXGBACK)
nback = MY_MAXGBACK;
if(nback > 0)
::memmove((char*)(m_gbuf - nback), (egptr() - nback), ...
// Fill the new data in read area.
int n;
if((n = ::recv(m_socket, m_gbuf, MY_GBUFSIZE, 0)) <= 0)
return std::char_traits<char>::eof();
this->setg((char*)(m_gbuf - nback), (char*)m_gbuf, (cha...
c = (int)m_gbuf[0]; c &= 255;
return c;
}
int
tcpbuffer::overflow(int c)
{
if(m_socket == INVALID_SOCKET)
return std::char_traits<char>::eof();
// Try to make rooms to put a new character
int npend = (int)(pptr() - (char*)m_pbuf);
if(npend < 0)
return std::char_traits<char>::eof();
if(npend > 0)
{
int nsend = ::send(m_socket, m_pbuf, npend, 0);
if(nsend <= 0)
return std::char_traits<char>::eof();
npend -= nsend;
if(npend > 0)
{
// Oooops!! Still we have pending data.
// Move the pending data to the beginning of
// the buffer to send them in next time.
::memmove(m_pbuf, (m_pbuf + nsend), npend);
}
}
this->setp((char*)(m_pbuf + npend), (char*)(m_pbuf + MY...
if(c == std::char_traits<char>::eof())
return 0;
*pptr() = (char)(c & 255);
pbump(1);
return c;
}
int
tcpbuffer::sync(void)
{
if(m_socket == INVALID_SOCKET)
return (-1);
int nleft = (int)(pptr() - (char*)m_pbuf);
int nsend;
char* p = m_pbuf;
while( nleft > 0 )
{
nsend = ::send(m_socket, p, nleft, 0);
if( nsend <= 0 )
return (-1);
nleft -= nsend;
p += nsend;
}
setp((char*)m_pbuf, (char*)(m_pbuf + MY_PBUFSIZE));
return 0;
}
} // namespace mynetlibrary
終了行:
[[C++のiostream]]
* C++ iostream 実装例 その 7 [#dde2b5e9]
前節([[C++ iostream 実装例 その 6]])で、必要な機能は全部...
押し込めた。ここまでくれば、iostream 化は容易である。
まず名前であるが、tcpstream としてもよいのだが、tcpclient...
TCP の stream には他にも、例えば accept が返す socket に...
が考えられるからである。
fstream に習って、constructor は
- tcpclient();
- tcpclient(const char* host, int port);
の二つ。いずれも例外を throw することはない。
独自に実装する member 関数も fstream に習って
- tcpclient* rdbuf() const;
- void connect(const char* host, int port);
- void close();
- bool is_connect() const;
の4つとする。
** 修正 2010-01-13 [#j40cbd5d]
- sync() の return の前に setp() による位置調整が必要。加...
** 概要 [#u861df0a]
基本的には、tcpclient は tcpbuffer を member 変数として保...
tcpclient に独自に実装する関数は、tcpbuffer の関数を呼び...
だけである。この時、connect() 及び close() はその結果によ...
failbit を設定する。
connect() まで行う constructor にあっても同様である。
この bit を設定すると、基底 class の iostream で exceptio...
判定して、exception を throw するかどうかを決めるので、派...
実装する必要は無い。
** header file [#q0c4d474]
この class のための include file を別に作ってもよいのだが、
tcpbuffer とは切っても切れない関係なので、
前の mytcpbuf.h に追加する形にして、ここでは mytcplib.h ...
一つの file にまとめる。
// mytcplib.h
#ifndef MY_TCPLIBRARY_H_INCLUDED
#define MY_TCPLIBRARY_H_INCLUDED
#ifdef WINSOCK
#include <winsock2.h>
#include <ws2tcpip.h>
#endif // WINSOCK
#include <streambuf>
#include <iostream>
namespace mynetlibrary
{
#ifndef WINSOCK
typedef int SOCKET;
#endif // WINSOCK
class netlibrary
{
public:
netlibrary(void);
~netlibrary(void);
private:
static bool m_libloaded;
};
class tcpbuffer :
public std::streambuf
{
public:
tcpbuffer(void);
virtual ~tcpbuffer(void);
bool is_connect(void) const;
int connect(const char* host, int port);
int close(void);
protected:
virtual int underflow(void);
virtual int overflow(int c = std::char_traits<char>::eo...
virtual int sync(void);
private:
tcpbuffer(const tcpbuffer& src);
tcpbuffer& operator=(const tcpbuffer& src);
protected:
#ifndef WINSOCK
static const int INVALID_SOCKET = (-1);
#endif // WINSOCK
static const int MY_MAXGBACK = 128;
static const int MY_GBUFSIZE = 1024;
static const int MY_PBUFSIZE = 1024;
protected:
SOCKET m_socket;
char* m_gbuf;
char m_rbuf[(MY_MAXGBACK + MY_GBUFSIZE + 1)];
char m_pbuf[(MY_PBUFSIZE + 1)];
};
class tcpclient :
public std::iostream
{
public:
tcpclient(void);
tcpclient(const char* host, int port);
tcpbuffer* rdbuf(void) const;
void connect(const char* host, int port);
void close(void);
bool is_connect(void) const;
private:
tcpclient(const tcpclient& src);
tcpclient& operator=(const tcpclient& src);
protected:
tcpbuffer m_tcpbuf;
};
} // namespace mynetlibrary
#endif // MY_TCPLIBRARY_H_INCLUDED
** source file [#la17886e]
定義の方は、簡単である。
// mytcpcli.cpp
#include "mytcplib.h"
namespace mynetlibrary
{
tcpclient::tcpclient(void) :
std::iostream(0)
{
this->init(&m_tcpbuf);
}
tcpclient::tcpclient(const char* host, int port) :
std::iostream(0)
{
this->init(&m_tcpbuf);
if(m_tcpbuf.connect(host, port) != 0)
this->setstate(std::ios::failbit);
else
this->clear();
}
tcpbuffer*
tcpclient::rdbuf(void) const
{
return const_cast<tcpbuffer*>(&m_tcpbuf);
}
void
tcpclient::connect(const char* host, int port)
{
if(m_tcpbuf.connect(host, port) != 0)
this->setstate(std::ios::failbit);
else
this->clear();
}
void
tcpclient::close(void)
{
if(m_tcpbuf.close() != 0)
this->setstate(std::ios::failbit);
else
this->clear();
}
bool
tcpclient::is_connect(void) const
{
return m_tcpbuf.is_connect();
}
} // namespace mynetlibrary
** sample programs [#ucc46599]
前の sample も書き換えてみよう。
// testbuf3.cpp
#include "mytcplib.h"
char linebuf[4096];
int
main(int argc, char* argv[])
{
mynetlibrary::netlibrary lib;
if(argc != 2)
{
std::cerr << "Usage: " << argv[0] << " host" << std::e...
return (-1);
}
mynetlibrary::tcpclient tcpstream(argv[1], 80);
tcpstream << "GET / HTTP/1.0\r\n";
tcpstream << "Host: " << argv[1] << "\r\n";
tcpstream << "\r\n";
tcpstream.flush();
while(tcpstream.getline(linebuf, 4095))
{
std::streamsize n = tcpstream.gcount();
linebuf[n] = 0;
std::cout << linebuf << std::endl;
}
std::cout.flush();
return 0;
}
前に fstream でやった try-catch の例も、全く対称に書ける。
// testbuf4.cpp
#include "mytcplib.h"
char linebuf[4096];
int
main(int argc, char* argv[])
{
mynetlibrary::netlibrary lib;
if(argc != 2)
{
std::cerr << "Usage: " << argv[0] << " host" << std::e...
return (-1);
}
mynetlibrary::tcpclient tcpstream;
tcpstream.exceptions(mynetlibrary::tcpclient::badbit | ...
try
{
tcpstream.connect(argv[1],80);
tcpstream << "GET / HTTP/1.0\r\n";
tcpstream << "Host: " << argv[1] << "\r\n";
tcpstream << "\r\n";
tcpstream.flush();
while(tcpstream.getline(linebuf, 4095))
{
std::streamsize n = tcpstream.gcount();
linebuf[n] = 0;
std::cout << linebuf << std::endl;
}
std::cout.flush();
}
catch(mynetlibrary::tcpclient::failure& e)
{
std::cerr << "Failure: " << e.what() << std::endl;
}
return 0;
}
** 補足 [#d339ae34]
mytcpbuf.cpp の方も(本質的ではないが)若干書き換えたので...
// mytcpbuf.cpp
#ifndef WINSOCK
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif // WINSOCK
#include "mytcplib.h"
namespace mynetlibrary
{
bool
netlibrary::m_libloaded = false;
netlibrary::netlibrary(void)
{
if(m_libloaded)
return;
#ifdef WINSOCK
WORD wVersion;
WSADATA wsaData;
wVersion = MAKEWORD(2,2);
if(::WSAStartup( wVersion, &wsaData ))
m_libloaded = false;
else
m_libloaded = true;
#else // WINSOCK
m_libloaded = true;
#endif // WINSOCK
}
netlibrary::~netlibrary(void)
{
if(!m_libloaded)
return;
#ifdef WINSOCK
::WSACleanup();
#endif // WINSOCK
m_libloaded = false;
}
tcpbuffer::tcpbuffer(void)
{
m_socket = INVALID_SOCKET;
m_gbuf = m_rbuf + MY_MAXGBACK;
this->setg((char*)m_gbuf, (char*)m_gbuf, (char*)m_gbuf);
this->setp((char*)m_pbuf, (char*)(m_pbuf + MY_PBUFSIZE));
}
tcpbuffer::~tcpbuffer(void)
{
this->close();
}
bool
tcpbuffer::is_connect(void) const
{
if(m_socket == INVALID_SOCKET)
return false;
return true;
}
int
tcpbuffer::connect(const char* host, int port)
{
// Returns 0 if success, otherwise returns non-zero.
if(m_socket != INVALID_SOCKET)
return (-1); // already conected
m_socket = ::socket(PF_INET, SOCK_STREAM, 0);
if(m_socket == INVALID_SOCKET)
return (-2);
#ifndef USE_GETHOSTBYNAME
struct sockaddr_in srvaddr;
struct sockaddr_in* resaddr;
struct addrinfo hints;
struct addrinfo* restop;
struct addrinfo* res;
int err;
res = 0;
::memset((char*)&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if((err = ::getaddrinfo(host, 0, &hints, &restop)) != 0)
{
this->close();
return (-3);
}
res = restop;
while(res)
{
resaddr = (struct sockaddr_in*)res->ai_addr;
::memset((char*)&srvaddr, 0, sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = ::htons((u_short)port);
srvaddr.sin_addr = resaddr->sin_addr;
if(::connect(m_socket, (struct sockaddr*)&srvaddr, siz...
break;
res = res->ai_next;
}
::freeaddrinfo(restop);
if(!res)
{
this->close();
return (-4);
}
#else // USE_GETHOSTBYNAME
struct sockaddr_in srvaddr;
unsigned long inaddr;
struct hostent *hp;
::memset((char*)&srvaddr, 0, sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = ::htons((u_short)port);
if((inaddr = ::inet_addr(host)) != INADDR_NONE)
{
::memcpy((char*)&srvaddr.sin_addr, (char*)&inaddr, siz...
if(::connect(m_socket, (struct sockaddr*)&srvaddr, siz...
{
this->close();
return (-3);
}
}
else
{
if((hp = ::gethostbyname(host)) == 0)
{
this->close();
return (-4);
}
if(hp->h_addrtype != AF_INET)
{
this->close();
return (-5);
}
const char** addr = (const char**)hp->h_addr_list;
while(*addr)
{
::memcpy((char*)&srvaddr.sin_addr, (char*)(*addr), hp...
if(::connect(m_socket, (struct sockaddr*)&srvaddr, si...
break;
++addr;
}
if(*addr == 0)
{
this->close();
return (-6);
}
}
#endif // USE_GETHOSTBYNAME
return 0;
}
int
tcpbuffer::close(void)
{
if(m_socket == INVALID_SOCKET)
return -1;
int ret;
#ifndef WINSOCK
ret = ::close(m_socket);
#else // WINSOCK
ret = ::closesocket(m_socket);
#endif // WINSOCK
m_socket = INVALID_SOCKET;
return ret;
}
int
tcpbuffer::underflow(void)
{
if(m_socket == INVALID_SOCKET)
return std::char_traits<char>::eof();
int c;
if((gptr() >= (char*)m_gbuf) && (gptr() < egptr()))
{
// Why call me ?
// Still we have enough data in the buffer.
c = (int)*gptr(); c &= 255;
return c;
}
// Move the previos (tail) data in backup area.
int nback = (int)(egptr() - eback());
if(nback > MY_MAXGBACK)
nback = MY_MAXGBACK;
if(nback > 0)
::memmove((char*)(m_gbuf - nback), (egptr() - nback), ...
// Fill the new data in read area.
int n;
if((n = ::recv(m_socket, m_gbuf, MY_GBUFSIZE, 0)) <= 0)
return std::char_traits<char>::eof();
this->setg((char*)(m_gbuf - nback), (char*)m_gbuf, (cha...
c = (int)m_gbuf[0]; c &= 255;
return c;
}
int
tcpbuffer::overflow(int c)
{
if(m_socket == INVALID_SOCKET)
return std::char_traits<char>::eof();
// Try to make rooms to put a new character
int npend = (int)(pptr() - (char*)m_pbuf);
if(npend < 0)
return std::char_traits<char>::eof();
if(npend > 0)
{
int nsend = ::send(m_socket, m_pbuf, npend, 0);
if(nsend <= 0)
return std::char_traits<char>::eof();
npend -= nsend;
if(npend > 0)
{
// Oooops!! Still we have pending data.
// Move the pending data to the beginning of
// the buffer to send them in next time.
::memmove(m_pbuf, (m_pbuf + nsend), npend);
}
}
this->setp((char*)(m_pbuf + npend), (char*)(m_pbuf + MY...
if(c == std::char_traits<char>::eof())
return 0;
*pptr() = (char)(c & 255);
pbump(1);
return c;
}
int
tcpbuffer::sync(void)
{
if(m_socket == INVALID_SOCKET)
return (-1);
int nleft = (int)(pptr() - (char*)m_pbuf);
int nsend;
char* p = m_pbuf;
while( nleft > 0 )
{
nsend = ::send(m_socket, p, nleft, 0);
if( nsend <= 0 )
return (-1);
nleft -= nsend;
p += nsend;
}
setp((char*)m_pbuf, (char*)(m_pbuf + MY_PBUFSIZE));
return 0;
}
} // namespace mynetlibrary
ページ名: