From bc0f05e4b47b573f1af45f5a80a167aec01b4f15 Mon Sep 17 00:00:00 2001 From: Arjen Baart Date: Wed, 31 Oct 2012 15:32:46 +0100 Subject: [PATCH] First implementation of socket stream classes derived from iostream classes. --- include/sockstream.h | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/Makefile.am | 16 +++- test/intest.cpp | 61 +++++++++++++++ test/iptest.cpp | 33 -------- test/outtest.cpp | 61 +++++++++++++++ test/stream | 36 +++++++++ 6 files changed, 389 insertions(+), 35 deletions(-) create mode 100644 include/sockstream.h create mode 100644 test/intest.cpp create mode 100644 test/outtest.cpp create mode 100755 test/stream diff --git a/include/sockstream.h b/include/sockstream.h new file mode 100644 index 0000000..d6352af --- /dev/null +++ b/include/sockstream.h @@ -0,0 +1,217 @@ +/************************************************************************** +** (c) Copyright 2012, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : sockstream.h +** SYSTEM NAME : Socket stream classes +** VERSION NUMBER : 0.1 +** +** DESCRIPTION : sockbuf and sockstream classes. +** +** EXPORTED OBJECTS : class sockbuf, class isockstream, +** class osockstream, class sockstream +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Aug 16, 2012 +** LAST UPDATE : Oct 19, 2012 +** MODIFICATIONS : +**************************************************************************/ + +#include +#include "socket.h" + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +** NAME : basic_sockbuf - Template class that applies basic_streambuf to sockets. +** MEMBERS : sock : Socket object that holds the network socket. +** OPERATORS : None +** METHODS : connect() : Connect the sockbuf to a Socket object. +** close() : Close the UNIX file descriptor in the Socket. +** overflow() : Override the base class function overflow. +** underflow() : Override the base class function underflow. +** +** DESCRIPTION : +** +** +** RELATIONS : std::basic_streambuf, Socket +** SEE ALSO : +** LAST MODIFIED : Oct 19, 2012 +**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + +#define SOCKBUFSIZE 1500 + +template > + class basic_sockbuf : public std::basic_streambuf<_CharT, _Traits> +{ +private: + StreamSocket sock; + + _CharT gbuf[SOCKBUFSIZE]; + _CharT pbuf[SOCKBUFSIZE]; + +public: + + basic_sockbuf() + { + setg(gbuf,gbuf+SOCKBUFSIZE,gbuf+SOCKBUFSIZE); // set get area + setp(pbuf,pbuf+SOCKBUFSIZE); // set put area + } + + virtual ~basic_sockbuf() + { + sync(); + } + + void connect(StreamSocket s) + { + sock = s; + } + + void close() + { + sock.Close(); + } + + virtual int underflow() + { + int bytes_read = sock.Read(gbuf, SOCKBUFSIZE); + if (bytes_read > 0) + { + setg(gbuf, gbuf, gbuf + bytes_read); + return 0; + } + else + { + return -1; + } + } + + virtual int overflow(int c) + { + sync(); + if (c != _Traits::eof() ) + { + *this->pptr() = c; + this->pbump(1); + } + return c; + } + + virtual int sync() + { + // check if there's data to flush + if (this->pptr() > this->pbase()) + { + sock.Write(pbuf, this->pptr() - pbuf); + setp(pbuf, pbuf + SOCKBUFSIZE); // reset put area + } + return 0; + } +}; + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +** NAME : basic_isockstream +** MEMBERS : +** OPERATORS : None +** METHODS : +** +** DESCRIPTION : +** +** +** RELATIONS : +** SEE ALSO : +** LAST MODIFIED : Oct 19, 2012 +**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + +template > + class basic_isockstream : public std::basic_istream<_CharT, _Traits> +{ +private: + basic_sockbuf<_CharT, _Traits> _M_sockbuf; + +public: + basic_isockstream(StreamSocket _s) + { + this->init(&_M_sockbuf); + _M_sockbuf.connect(_s); + } +}; + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +** NAME : basic_osockstream +** MEMBERS : +** OPERATORS : None +** METHODS : +** +** DESCRIPTION : +** +** +** RELATIONS : +** SEE ALSO : +** LAST MODIFIED : Oct 19, 2012 +**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + +template > + class basic_osockstream : public std::basic_ostream<_CharT,_Traits> +{ +private: + basic_sockbuf<_CharT, _Traits> _M_sockbuf; + +public: + basic_osockstream(StreamSocket _s) + { + this->init(&_M_sockbuf); + _M_sockbuf.connect(_s); + } +}; + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +** NAME : basic_sockstream +** MEMBERS : +** OPERATORS : None +** METHODS : +** +** DESCRIPTION : +** +** +** RELATIONS : +** SEE ALSO : +** LAST MODIFIED : Oct 19, 2012 +**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + +template > + class basic_sockstream : public std::basic_iostream<_CharT, _Traits> +{ +private: + basic_sockbuf<_CharT, _Traits> _M_sockbuf; + +public: + basic_sockstream(StreamSocket _s) + { + this->init(&_M_sockbuf); + _M_sockbuf.connect(_s); + } +}; + + +// Predefined buffer and stream types + +typedef basic_sockbuf sockbuf; +typedef basic_isockstream isockstream; +typedef basic_osockstream osockstream; +typedef basic_sockstream sockstream; + +typedef basic_sockbuf wsockbuf; +typedef basic_isockstream wisockstream; +typedef basic_osockstream wosockstream; +typedef basic_sockstream wsockstream; + diff --git a/test/Makefile.am b/test/Makefile.am index 6396368..24b5c6c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,11 +1,23 @@ -check_PROGRAMS = iptest revd +check_PROGRAMS = iptest revd intest outtest http_get iptest_SOURCES = iptest.cpp iptest_CPPFLAGS = -I$(top_srcdir)/include iptest_LDADD = $(top_builddir)/src/libsockstream.la +http_get_SOURCES = iptest.cpp +http_get_CPPFLAGS = -I$(top_srcdir)/include +http_get_LDADD = $(top_builddir)/src/libsockstream.la + revd_SOURCES = revd.cpp revd_CPPFLAGS = -I$(top_srcdir)/include revd_LDADD = $(top_builddir)/src/libsockstream.la -TESTS = iptest revd +intest_SOURCES = intest.cpp +intest_CPPFLAGS = -I$(top_srcdir)/include +intest_LDADD = $(top_builddir)/src/libsockstream.la + +outtest_SOURCES = outtest.cpp +outtest_CPPFLAGS = -I$(top_srcdir)/include +outtest_LDADD = $(top_builddir)/src/libsockstream.la + +TESTS = iptest stream diff --git a/test/intest.cpp b/test/intest.cpp new file mode 100644 index 0000000..015d3b5 --- /dev/null +++ b/test/intest.cpp @@ -0,0 +1,61 @@ +/************************************************************************** +** (c) Copyright 2012, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : intest.cpp +** SYSTEM NAME : Network and socket classes - test routine +** VERSION NUMBER : 0.1 +** +** DESCRIPTION : Input stream test. +** Connects to TCP port 1234 and reads a line. +** Test with: echo "this is a test"|nc -l 1234 +** +** EXPORTED OBJECTS : +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Oct 19, 2012 +** LAST UPDATE : Oct 29, 2012 +** MODIFICATIONS : +**************************************************************************/ + +#include "sockstream.h" + + +/*========================================================================= +** NAME : main +** SYNOPSIS : +** PARAMETERS : +** RETURN VALUE : None +** +** DESCRIPTION : Read lines of text from port 1234 and echo these lines +** to cout. +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : Oct 29, 2012 +**========================================================================= +*/ + +int main() +{ + IPSocketAddress serveraddress(InternetAddress("127.0.0.1"), Port(1234)); + + StreamSocket s; + + s.Connect(serveraddress); + isockstream reader(s); + + String buf; + while (reader >> buf) + { + std::cout << buf << "\n"; + } +} + diff --git a/test/iptest.cpp b/test/iptest.cpp index 221b0fe..48dd6d9 100644 --- a/test/iptest.cpp +++ b/test/iptest.cpp @@ -51,39 +51,6 @@ int main() std::cout << String(ip) << "\n"; - std::cout << "Finding www.noortict.nl\n"; - Host server(String("www.noortict.nl")); - std::list iplist = server.FindAddress(); - std::list::iterator ipaddress; - for (ipaddress = iplist.begin(); ipaddress != iplist.end(); ipaddress++) - { - std::cout << " IP address " << String(*ipaddress) << "\n"; - } - - Service srv("http"); - std::list portlist = srv.FindAddress(); - std::list::iterator port; - for (port = portlist.begin(); port != portlist.end(); port++) - { - std::cout << " Port " << port->get_port() << ", socket type " << port->get_sockettype() << "\n"; - } - - IPSocketAddress serveraddress(iplist.front(), portlist.front()); - StreamSocket s; - - std::cout << "Connection result = " << s.Connect(serveraddress) << "\n"; - s.Write("GET / HTTP/1.1\n", 15); - s.Write("Host: www.noortict.nl\n\n", 23); - - char buf[1000]; - int len; - do - { - len = s.Read(buf, 1000); - buf[len] = '\0'; - std::cout << "LEN = " << len << "\n" << buf << "\n"; - } - while (len > 0); } diff --git a/test/outtest.cpp b/test/outtest.cpp new file mode 100644 index 0000000..114c3e3 --- /dev/null +++ b/test/outtest.cpp @@ -0,0 +1,61 @@ +/************************************************************************** +** (c) Copyright 2012, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : outtest.cpp +** SYSTEM NAME : Network and socket classes - test routine +** VERSION NUMBER : 0.1 +** +** DESCRIPTION : Output stream test. +** Connects to TCP port 1234 and writes a line. +** Test with: nc -l 1234 +** +** EXPORTED OBJECTS : +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Oct 19, 2012 +** LAST UPDATE : Oct 30, 2012 +** MODIFICATIONS : +**************************************************************************/ + +#include "sockstream.h" + + +/*========================================================================= +** NAME : main +** SYNOPSIS : +** PARAMETERS : +** RETURN VALUE : None +** +** DESCRIPTION : Read lines of text from port 1234 and echo these lines +** to cout. +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : Oct 29, 2012 +**========================================================================= +*/ + +int main() +{ + IPSocketAddress serveraddress(InternetAddress("127.0.0.1"), Port(1234)); + + StreamSocket s; + + s.Connect(serveraddress); + osockstream writer(s); + + String buf; + while (std::cin >> buf) + { + writer << buf << std::endl; + } +} + diff --git a/test/stream b/test/stream new file mode 100755 index 0000000..261d184 --- /dev/null +++ b/test/stream @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Test script for socket stream classes. +# Use a few test programs to test stream communication +# through sockets. +# + +TESTSTRING="this is a test" + +# +# Test the iscokstream class +# + +echo $TESTSTRING|nc -l 1234 & +OUT=$(./intest) +if [ "$OUT" = "$TESTSTRING" ] +then + echo " isockstream OK." +else + echo " isockstream Fail." +fi + +# +# Test the oscokstream class +# + +nc -l 1234 >stream.out& +echo $TESTSTRING |./outtest +read OUT