⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockstream.cpp

📁 最新osg包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// sockstream.C -*- C++ -*- socket library// Copyright (C) 2002 Herbert Straub for my changes, see ChangeLog.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.// // Copyright (C) 1992-1996 Gnanasekaran Swaminathan <gs4t@virginia.edu>//// Permission is granted to use at your own risk and distribute this software// in source and  binary forms provided  the above copyright notice and  this// paragraph are  preserved on all copies.  This software is provided "as is"// with no express or implied warranty.//// Version: 12Jan97 1.11//// You can simultaneously read and write into// a sockbuf just like you can listen and talk// through a telephone. Hence, the read and the// write buffers are different. That is, they do not// share the same memory.// // Read:// gptr() points to the start of the get area.// The unread chars are gptr() - egptr().// base() points to the read buffer// // eback() is set to base() so that pbackfail()// is called only when there is no place to// putback a char. And pbackfail() always returns EOF.// // Write:// pptr() points to the start of the put area// The unflushed chars are pbase() - pptr()// pbase() points to the write buffer.// epptr() points to the end of the write buffer.// // Output is flushed whenever one of the following conditions// holds:// (1) pptr() == epptr()// (2) EOF is written// (3) linebuffered and '\n' is written// // Unbuffered:// Input buffer size is assumed to be of size 1 and output// buffer is of size 0. That is, egptr() <= base()+1 and// epptr() == pbase().//// Version: 1.2 2002-07-25 Herbert Straub // Improved Error Handling - extending the sockerr class by cOperation#include "sockstream.h"#include <sstream>#include <string>#if defined(__CYGWIN__) || !defined(WIN32)extern "C" {#    include <sys/time.h>#    include <sys/socket.h>#    include <sys/ioctl.h>#    include <unistd.h>#    include <errno.h>}#else#   if (_MSC_VER >= 1400)#      include <errno.h>#   endif#   define EWOULDBLOCK          WSAEWOULDBLOCK#   define EINPROGRESS          WSAEINPROGRESS#   define EALREADY             WSAEALREADY#   define ENOTSOCK             WSAENOTSOCK#   define EDESTADDRREQ         WSAEDESTADDRREQ#   define EMSGSIZE             WSAEMSGSIZE#   define EPROTOTYPE           WSAEPROTOTYPE#   define ENOPROTOOPT          WSAENOPROTOOPT#   define EPROTONOSUPPORT      WSAEPROTONOSUPPORT#   define ESOCKTNOSUPPORT      WSAESOCKTNOSUPPORT#   define EOPNOTSUPP           WSAEOPNOTSUPP#   define EPFNOSUPPORT         WSAEPFNOSUPPORT#   define EAFNOSUPPORT         WSAEAFNOSUPPORT#   define EADDRINUSE           WSAEADDRINUSE#   define EADDRNOTAVAIL        WSAEADDRNOTAVAIL#   define ENETDOWN             WSAENETDOWN#   define ENETUNREACH          WSAENETUNREACH#   define ENETRESET            WSAENETRESET#   define ECONNABORTED         WSAECONNABORTED#   define ECONNRESET           WSAECONNRESET#   define ENOBUFS              WSAENOBUFS#   define EISCONN              WSAEISCONN#   define ENOTCONN             WSAENOTCONN#   define ESHUTDOWN            WSAESHUTDOWN#   define ETOOMANYREFS         WSAETOOMANYREFS#   define ETIMEDOUT            WSAETIMEDOUT#   define ECONNREFUSED         WSAECONNREFUSED#   define ELOOP                WSAELOOP#   define EHOSTDOWN            WSAEHOSTDOWN#   define EHOSTUNREACH         WSAEHOSTUNREACH#   define EPROCLIM             WSAEPROCLIM#   define EUSERS               WSAEUSERS#   define EDQUOT               WSAEDQUOT#   define EISCONN              WSAEISCONN#   define ENOTCONN             WSAENOTCONN#   define ECONNRESET           WSAECONNRESET#   define ECONNREFUSED         WSAECONNREFUSED#   define ETIMEDOUT            WSAETIMEDOUT#   define EADDRINUSE           WSAEADDRINUSE#   define EADDRNOTAVAIL        WSAEADDRNOTAVAIL#   define EWOULDBLOCK          WSAEWOULDBLOCK#endif // !WIN32#ifdef __sun#include <sys/sockio.h>#include <sys/filio.h>#endif#ifndef BUFSIZ#  define BUFSIZ 1024#endif#ifdef FD_ZERO#  undef FD_ZERO    // bzero causes so much trouble to us#endif#define FD_ZERO(p) (memset ((p), 0, sizeof *(p)))// Do not include anything below that define. That should in no case change any forward decls in// system headers ...#if (defined(__APPLE__)&&(__GNUC__<4)) || (defined(WIN32)&&!defined(__CYGWIN__)) || \ (!defined(__APPLE__) && !defined(WIN32) && !defined(_XOPEN_SOURCE_EXTENDED) && !defined(__FreeBSD__))#define socklen_t int#endifconst char* sockerr::errstr () const{#if defined(__CYGWIN__) || !defined(WIN32)    return strerror(err);#else    return 0; // TODO#endif}bool sockerr::io () const// recoverable io error.{  switch (err) {  case EWOULDBLOCK:  case EINPROGRESS:  case EALREADY:    return true;  }  return false;}bool sockerr::arg () const// recoverable argument error.{  switch (err) {  case ENOTSOCK:  case EDESTADDRREQ:  case EMSGSIZE:  case EPROTOTYPE:  case ENOPROTOOPT:  case EPROTONOSUPPORT:  case ESOCKTNOSUPPORT:  case EOPNOTSUPP:  case EPFNOSUPPORT:  case EAFNOSUPPORT:  case EADDRINUSE:  case EADDRNOTAVAIL:    return true;  }  return false;}bool sockerr::op () const// operational error encountered {  switch (err) {  case ENETDOWN:  case ENETUNREACH:  case ENETRESET:  case ECONNABORTED:  case ECONNRESET:  case ENOBUFS:  case EISCONN:  case ENOTCONN:  case ESHUTDOWN:  case ETOOMANYREFS:  case ETIMEDOUT:  case ECONNREFUSED:  case ELOOP:  case ENAMETOOLONG:  case EHOSTDOWN:  case EHOSTUNREACH:  case ENOTEMPTY:#   if !defined(__linux__) && !defined(__sun) && !defined(__hpux)// LN  case EPROCLIM:#   endif  case EUSERS:  case EDQUOT:    return true;  }  return false;}bool sockerr::conn () const// return true if err is EISCONN, ENOTCONN, ECONNRESET, ECONNREFUSED,// ETIMEDOUT, or EPIPE{  switch (err) {  case EISCONN:  case ENOTCONN:  case ECONNRESET:  case ECONNREFUSED:  case ETIMEDOUT:  case EPIPE:    return true;  }  return false;}bool sockerr::addr () const// return true if err is EADDRINUSE or EADDRNOTAVAIL{  switch (err) {  case EADDRINUSE:  case EADDRNOTAVAIL:    return true;  }  return false;}bool sockerr::benign () const// return true if err is EINTR, EWOULDBLOCK, or EAGAIN{  switch (err) {  case EINTR:  case EWOULDBLOCK:#if defined(EAGAIN) && (EAGAIN != EWOULDBLOCK)  case EAGAIN:#endif    return true;  }  return false;}sockbuf::sockbuf (const sockbuf::sockdesc& sd)//  : rep (new sockbuf::sockcnt (sd.sock)){  rep = new sockbuf::sockcnt (sd.sock);  char_type* gbuf = new char_type [BUFSIZ];  char_type* pbuf = new char_type [BUFSIZ];  setg (gbuf, gbuf + BUFSIZ, gbuf + BUFSIZ);  setp (pbuf, pbuf + BUFSIZ);  rep->gend = gbuf + BUFSIZ;  rep->pend = pbuf + BUFSIZ;}   sockbuf::sockbuf (int domain, sockbuf::type st, int proto)  : rep (0){#if defined(WIN32) && !defined(__CYGWIN__)  WORD version = MAKEWORD(1,1);  WSADATA wsaData;  WSAStartup(version, &wsaData);#endif  SOCKET soc = ::socket (domain, st, proto);    if (soc == static_cast<SOCKET>(SOCKET_ERROR))#if defined(__CYGWIN__) || !defined(WIN32)    throw sockerr (errno, "sockbuf::sockbuf");#else    throw sockerr(WSAGetLastError(), "sockbuf::sockbuf");#endif  rep = new sockbuf::sockcnt (soc);    char_type* gbuf = new char_type [BUFSIZ];  char_type* pbuf = new char_type [BUFSIZ];  setg (gbuf, gbuf + BUFSIZ, gbuf + BUFSIZ);  setp (pbuf, pbuf + BUFSIZ);  rep->gend = gbuf + BUFSIZ;  rep->pend = pbuf + BUFSIZ;}sockbuf::sockbuf (const sockbuf& sb):streambuf(),//streambuf (sb),rep (sb.rep){  // the streambuf::streambuf (const streambuf&) is assumed  // to haved handled pbase () and gbase () correctly.  rep->cnt++; }/*sockbuf& sockbuf::operator = (const sockbuf& sb){  if (this != &sb && rep != sb.rep && rep->sock != sb.rep->sock) {    streambuf::operator = (sb);    this->sockbuf::~sockbuf();    // the streambuf::operator = (const streambuf&) is assumed    // to have handled pbase () and gbase () correctly.    rep  = sb.rep;    rep->cnt++;  }  return *this;}*/sockbuf::~sockbuf (){  overflow (eof); // flush write buffer  if (--rep->cnt == 0) {    delete [] pbase ();    delete [] eback ();#if defined(__CYGWIN__) || !defined(WIN32)    int c = close (rep->sock);#else    int c = closesocket(rep->sock);#endif    delete rep;    if (c == SOCKET_ERROR) #if defined(__CYGWIN__) || !defined(WIN32)    throw sockerr (errno, "sockbuf::~sockbuf", sockname.c_str());#else    throw sockerr(WSAGetLastError(), "sockbuf::~sockbuf", sockname.c_str());#endif  }}bool sockbuf::is_open () const// if socket is still connected to the peer, return true// else return false{    return false;}int sockbuf::sync ()// we never return -1 because we throw sockerr// exception in the event of an error.{    if (pptr () && pbase () < pptr () && pptr () <= epptr ())    {        // we have some data to flush        try {            write (pbase (), pptr () - pbase ());        }        catch (int wlen)        {            // write was not completely successful            stringstream sb;            string err ("sockbuf::sync");            err += "(" + sockname + ")";            if (wlen) {                // reposition unwritten chars                char* pto = pbase ();                char* pfrom = pbase () + wlen;                int len = pptr () - pbase () - wlen;                while (pfrom < pptr ()) *pto++ = *pfrom++;                setp (pbase (), (char_type*) rep->pend);                pbump (len);                sb << " wlen=(" << wlen << ")";                err += sb.rdbuf()->str();            }            throw sockerr (errno, err.c_str ());        }        setp (pbase (), (char_type*) rep->pend);    }    // we cannot restore input data back to the socket stream    // thus we do not do anything on the input stream    return 0;}int sockbuf::showmanyc () const// return the number of chars in the input sequence{    if (gptr () && gptr () < egptr ())        return egptr () - gptr ();    return 0;}sockbuf::int_type sockbuf::underflow (){  if (gptr () == 0)    return eof; // input stream has been disabled  if (gptr () < egptr ())    return (unsigned char) *gptr (); // eof is a -ve number; make it                                     // unsigned to be diff from eof  int rlen = read (eback (), (char*) rep->gend - (char*) eback ());  if (rlen == 0)    return eof;  setg (eback (), eback (), eback () + rlen);  return (unsigned char) *gptr ();}sockbuf::int_type sockbuf::uflow (){  int_type ret = underflow ();  if (ret == eof)    return eof;  gbump (1);  return ret;}streamsize sockbuf::xsgetn (char_type* s, streamsize n){  int rval = showmanyc ();  if (rval >= n) {    memcpy (s, gptr (), n * sizeof (char_type));    gbump (n);    return n;  }  memcpy (s, gptr (), rval * sizeof (char_type));  gbump (rval);  if (underflow () != eof)    return rval + xsgetn (s + rval, n - rval);    return rval;}sockbuf::int_type sockbuf::pbackfail (int){  return eof;}sockbuf::int_type sockbuf::overflow (sockbuf::int_type c)// if pbase () == 0, no write is allowed and thus return eof.// if c == eof, we sync the output and return 0.// if pptr () == epptr (), buffer is full and thus sync the output,//                         insert c into buffer, and return c.// In all cases, if error happens, throw exception.{  if (pbase () == 0)    return eof;  if (c == eof)    return sync ();  if (pptr () == epptr ())    sync ();  *pptr () = (char_type)c;  pbump (1);  return c;}streamsize sockbuf::xsputn (const char_type* s, streamsize n){  int wval = epptr () - pptr ();  if (n <= wval) {    memcpy (pptr (), s, n * sizeof (char_type));    pbump (n);    return n;  }  memcpy (pptr (), s, wval * sizeof (char_type));  pbump (wval);    if (overflow () != eof)    return wval + xsputn (s + wval, n - wval);  return wval;}void sockbuf::bind (sockAddr& sa){  if (::bind (rep->sock, sa.addr (), sa.size ()) == -1)    throw sockerr (errno, "sockbuf::bind", sockname.c_str());}void sockbuf::connect (sockAddr& sa){  if (::connect(rep->sock, sa.addr (), sa.size()) == -1)    throw sockerr (errno, "sockbuf::connect", sockname.c_str());}void sockbuf::listen (int num){  if (::listen (rep->sock, num) == -1)    throw sockerr (errno, "sockbuf::listen", sockname.c_str());}sockbuf::sockdesc sockbuf::accept (sockAddr& sa){  socklen_t len = sa.size ();  int soc = -1;  if ((soc = ::accept (rep->sock, sa.addr (),                        &len)) == -1)    throw sockerr (errno, "sockbuf::sockdesc", sockname.c_str());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -