www.pudn.com > socketCppWrapper.zip > socket.h


/************************************************************************************ 
*                                                                                   * 
*    Title:  socket.h                                                               * 
*                                                                                   * 
*    Permission to use, copy,  modify and distribute this software and it's docu-   * 
*    mentation for any purpose and  without fee is hereby granted,  provided that   * 
*    this notice remain part of the source files. This package is provided as is,   * 
*    without any support.                                                           * 
*                                                                                   * 
*           Corrections and enhancements are welcome.                               * 
*           Author's address: meessen@cppm.in2p3.fr                                 * 
*                                                                                   * 
*                                                                                   * 
************************************************************************************* 
*                                                                                   * 
*    Autors: Christophe MEESSEN                                                     * 
*                                                                                   * 
*    Date: apr 1999                                                                 * 
*                                                                                   * 
*************************************************************************************/ 
 
 
// Note: an STL ios_baseTREAM compatible source of socket.h and an STL sockstream 
//       are also available. 
 
#ifndef _BASIC_SOCKET_ 
#define _BASIC_SOCKET_ 
 
#if _MSC_VER > 1000 
#pragma once 
#endif 
 
 
#include  
 
// OS Specific includes 
#ifdef WIN32 
	#include  
	#include  
	#include  
 
#else 
	#define BSD_COMP 
 
	#include  
	#include  
	#include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
 
extern "C"{   
        int gethostname(char*,int); 
} 
	#define SOCKET int 
	#define INADDR_NONE -1 
	#define SOCKET_ERROR -1 
	#define ioctlsocket ioctl 
	#define closesocket close 
	#define _STD_BEGIN 
	#define _STD_END 
 
 
	#ifdef _Linux__ 
		#define MSG_MAXIOVLEN	 16 
		#define SOMAXCONN	 5 
	#endif // _Linux__ 
#endif 
 
#ifdef  _MSC_VER 
#pragma pack(push,8) 
#endif  /* _MSC_VER */ 
 
// socket address classes (may be needed for unix) 
//struct sockaddr; 
 
#ifdef WIN32 
_STD_BEGIN 
#endif 
 
extern "C" { 
inline int sockInit() 
{ 
#ifdef WIN32 
	WSADATA d; 
	return ::WSAStartup( MAKEWORD( 2, 0 ), &d ); 
#else 
	return 0; 
#endif 
} 
} 
 
		// ABSTRACT SOCKADDR BASE CLASS 
class sockAddr { 
public: 
	virtual	~sockAddr() {} 
 
	virtual	operator	void*		() const =0; 
			operator	sockaddr*	() const { return addr(); } 
	virtual int			size 		() const =0; 
	virtual int			family		() const =0; 
	virtual sockaddr*	addr		() const =0; 
}; 
 
 
////////////////////////////////////////////////////////// 
// INTERNET SOCKET ADDRESS 
// Note: addresses and port numbers are in host byte order 
////////////////////////////////////////////////////////// 
class inetaddr: public sockAddr, public sockaddr_in { 
public: 
	enum {  
		any_addr  = INADDR_ANY, 
		loopback  = INADDR_LOOPBACK, 
		broadcast = INADDR_BROADCAST, 
		none_addr = INADDR_NONE  
	}; 
 
	virtual ~inetaddr() {} 
	// local host socket address 
	explicit inetaddr( int portno = 0 ) 
		{ sin_family = AF_INET; host(any_addr); port(portno); } 
	// remote host address or 'broadcast' or 'loopback' 
	explicit inetaddr( unsigned long addr, int portno ) 
		{ sin_family = AF_INET; host(addr); port(portno); } 
	// remote host named address 
	explicit inetaddr( const char* hostn, int portno ) 
		{ sockInit(); sin_family = AF_INET; host(hostn); port(portno); } 
	// local(addr=any_addr) or remote service 
	explicit inetaddr( unsigned long addr, const char* service, const char* proto="tcp" ) 
		{ sockInit(); sin_family = AF_INET; host(addr); port( service, proto ); } 
	// remote service 
	explicit inetaddr( const char* hostn, const char* service, const char* proto="tcp" ) 
		{ sockInit(); sin_family = AF_INET; host(hostn); port( service, proto ); } 
	inetaddr( const inetaddr &ia ) 
	{ 
		sin_family = AF_INET;  
		if( ia.isValid() ) 
		{ 
			sin_addr.s_addr = ia.addr_in()->sin_addr.s_addr; 
			sin_port = ia.addr_in()->sin_port; 
		} 
		else 
		{ 
			sin_port = (unsigned short)-1; sin_addr.s_addr = any_addr; 
		} 
	} 
	operator void*() const { return addr_in(); } 
	sockaddr_in* addr_in() const { return (sockaddr_in*)this; } 
	int size() const { return sizeof(sockaddr_in); } 
	int family() const { return sin_family; } 
	sockaddr* addr() const {return (sockaddr*) addr_in(); } 
 
	bool isValid() const { return (sin_family == AF_INET) && (sin_port != (unsigned short)-1); } 
 
	unsigned long hostaddr() const { return ntohl(sin_addr.s_addr);} 
	int port() const { return ntohs(sin_port); } 
	inetaddr& port( int portno ) { sin_port = htons(portno); return *this;} 
	inetaddr& port( const char* service, const char* proto = "tcp" ) 
	{ 
		servent *sp = ::getservbyname( service, proto ); 
		sin_port = sp?sp->s_port:-1; 
		return *this; 
	} 
 
	const char* host() const { 
		static char hn[64]; 
		hn[0] = '\0'; 
		if( isValid() ) 
		{ 
			switch( sin_addr.s_addr ){ 
			case any_addr: ::gethostname(hn, sizeof(hn)-1); return hn; 
			case loopback: ::strcpy( hn, "loopback" ); return hn; 
			case broadcast: :: strcpy( hn, "broadcast" ); return hn; 
			} 
			hostent *hp = ::gethostbyaddr( (const char*)&sin_addr, sizeof(sin_addr),sin_family ); 
			if( hp && hp->h_name ) return hp->h_name; 
			char*hs = inet_ntoa(sin_addr); 
			if( hs ) return hs; 
		} 
		return hn; 
	} 
	inetaddr& host( unsigned long addr ) { sin_addr.s_addr = addr; return *this;} 
	inetaddr& host( const char* hostn ) 
	{ 
		sin_addr.s_addr = ::inet_addr( hostn ); 
		if( sin_addr.s_addr == 0xFFFFFFFF ) 
		{ 
			hostent *hp = ::gethostbyname( hostn ); 
			if( hp ) 
				::memcpy( &sin_addr.s_addr, hp->h_addr, hp->h_length ); 
			else  
				sin_addr.s_addr = 0xFFFFFFFF; 
		} 
		return *this; 
	} 
}; 
 
 
class basic_socket { 
 
#undef _e 
#define _e char 
 
public: 
	typedef basic_socket _Myt; 
	typedef int int_type; 
	typedef int pos_type; 
	typedef int off_type; 
 
	friend class myst; 
 
	// CONSTANT DEFINITION 
 
	// socket stream types (see sockstream type tbl below) 
	enum socktype { 
		invalid_type, 
		inet_stream,	tcp  = inet_stream, 
		inet_dgram,		udp  = inet_dgram,			 
		inet_icmp,		icmp = inet_icmp,			 
		inet_raw,		raw  = inet_raw, 
		unix_stream,  
		unix_dgram  
	}; 
	 
	enum type { 
		sock_stream		= SOCK_STREAM, 
		sock_dgram		= SOCK_DGRAM, 
		sock_raw		= SOCK_RAW, 
		sock_rdm		= SOCK_RDM, 
		sock_seqpacket	= SOCK_SEQPACKET 
	}; 
 
	enum sockoption { 
		so_debug		= SO_DEBUG, 
		so_reuseaddr	= SO_REUSEADDR, 
		so_keepalive	= SO_KEEPALIVE, 
		so_dontroute	= SO_DONTROUTE, 
		sobufroadcast	= SO_BROADCAST, 
		soleninger		= SO_LINGER, 
		so_oobinline	= SO_OOBINLINE, 
		so_sndbuf		= SO_SNDBUF, 
		so_rcvbuf		= SO_RCVBUF, 
		so_error		= SO_ERROR, 
		so_type			= SO_TYPE 
	};	 
 
	enum { somaxconn	= SOMAXCONN }; 
 
	enum level { 
		sol_socket		= SOL_SOCKET 
	}; 
 
	enum shuthow { 
		shut_read, 
		shut_write, 
		shutbufoth 
	}; 
 
	// infinite time out limit and error code result 
	enum {  
		infinite		= -1,  
		invalid			= -1  
	}; 
 
	// default and minimal buffer size 
	enum bufsize{  
		minbsize		= 0,  
		defaultsize		= 1024,  
		maxbsize		= 65536  
	}; 
 
	struct socklinger  
	{ 
		int	l_onoff;	// option on/off 
		int	lleninger;	// linger time 
 
		socklinger (int a, int b): l_onoff (a), lleninger (b) {} 
	}; 
	 
	struct desc 
	{	 
		SOCKET sock; 
		explicit desc( SOCKET s )  : sock(s) {} 
	}; 
 
	// CONSTRUCTORS 
 
	// default constructor 
	basic_socket(): s(0), _tmo(false) {} 
 
	// socket buf copy initializer 
	basic_socket( const _Myt &sr ): _tmo(false) 
	{	 
		if( s = sr.sharedSocket() ) s->refcnt++; 
	} 
 
	// low level socket buf constructor  
	basic_socket( int file, type _t, int _p,  
		ios::openmode m = ios::in|ios::out ) : _tmo(false)  
	{ 
		sockInit(); s = new shared( ::socket( file, _t, _p), m ); 
	} 
 
	// The constructor you should use 
	explicit basic_socket( socktype st,  
		ios::openmode m = ios::in|ios::out ) : _tmo(false)  
	{ 
		const streamTypeDef &sd = getStreamType( st ); 
		bool connected = (st == _Myt::udp)||(st == _Myt::icmp)||(st == _Myt::raw); 
		sockInit();  
		s = new shared( ::socket( sd.family, sd.type, sd.protocol ), m, connected ); 
	} 
 
	// socket constructor using descriptor (used with accept) 
	basic_socket( const desc &_D,  
		ios::openmode m = ios::in|ios::out ) : _tmo(false) 
	{	 
		s = new shared( _D.sock, m, _D.sock != _Myt::invalid ); 
	} 
 
	// socket destructor 
	virtual ~basic_socket()  
	{  
		if( s && !--s->refcnt ) delete s; 
	} 
 
	_Myt& operator= ( const _Myt& sr ) 
	{ 
		if( s != sr.sharedSocket() && s && !--s->refcnt ) delete s; 
		if( s = sr.sharedSocket() ) s->refcnt++; 
		_tmo = 0; 
		return *this; 
	} 
 
	// UTILITY OPERATIONS 
	#ifdef WIN32 
	int errnum() const { return ::WSAGetLastError();} 
	#else 
	int errnum() const { return ::errno;} 
	#endif 
	bool timeout() const { return _tmo; } 
	bool isValid() const { return s && s->sock != _Myt::invalid; } 
	SOCKET sd() const { return s ? s->sock : _Myt::invalid; } 
	int sendtimeout( int msec ){ return s ? s->sendtimeout(msec) : _Myt::infinite; } 
	int recvtimeout( int msec ){ return s ? s->recvtimeout(msec) : _Myt::infinite; } 
	bool is_open( ios::openmode m = shared::open ) const  
		{ return s?(s->state&shared::open&m)!=0: false; } 
 
	// SOCKET OPERATIONS 
	bool listen( int _n = _Myt::somaxconn ) 
	{	 
		return ::listen( sd(), _n ) != _Myt::invalid; 
	} 
	bool bind( const sockAddr &sa ) 
	{  
		return ::bind( sd(), sa.addr(), sa.size() ) != _Myt::invalid; 
	} 
	bool connect( const sockAddr &sa ) 
	{ 
		bool buf = ::connect( sd(), sa.addr(), sa.size() ) != _Myt::invalid; 
		if( buf ) s->state |= shared::open; 
		return buf; 
	} 
	_Myt::desc accept( const sockAddr &sa ) 
	{ 
		int len = sa.size(); 
		return _Myt::desc(::accept( sd(), sa.addr(), &len )); 
	} 
	_Myt::desc accept() 
	{ 
		return _Myt::desc(::accept( sd(), 0, 0 ) ); 
	} 
	bool is_readready( int msec ) 
	{ 
		return s ? s->is_readready( msec, _tmo ) : false; 
	} 
	bool is_writeready( int msec )  
	{ 
		return s ? s->is_writeready( msec, _tmo ) : false; 
	} 
	bool is_exceptionpending( int msec )  
	{ 
		return s ? s->is_exceptionpending( msec, _tmo ) : false; 
	} 
 
	// DATA TRANSMISSION 
 
	// return number of received elements 
	// return 0 on error, timeout or connection closed or partial char received.  
	// Use is_open() or timeout() or errnum() to findout. 
	int_type recv( _e* buf, int_type len, int file = 0 ) 
	{ 
		return s ? s->recv( _tmo, buf, len, file ) : 0; 
	} 
	// return number of received elements 
	// return 0 on error, timeout or connection closed.  
	// Use is_open() or timeout() or errnum() to findout. 
	int_type recv( sockAddr &sa, _e* buf, int_type len, int file = 0 ) 
	{ 
		return s ? s->recv( _tmo, sa, buf, len, file ) : 0; 
	} 
	// return true if len elements have been received 
	// return false on error, timeout, connection closed or partial char received.  
	// Use is_open() or timeout() or errnum() to findout. 
	bool recvAll( _e* buf, int_type len, int file = 0 ) 
	{ 
		return s ? s->recvAll( _tmo, buf, len, file ) : false; 
	} 
	// return number of sent elements,  
	// this number is less than len on error, timeout or connection closed 
	// Use is_open() or timeout() or errnum() to findout. 
	int_type send( _e* buf, int_type len, int file = 0 ) 
	{ 
		return s ? s->send( _tmo, buf, len, file ) : 0; 
	} 
	// return number of sent elements,  
	// this number is less than len on error, timeout or connection closed 
	// Use is_open() or timeout() or errnum() to findout. 
	int_type send( sockAddr &sa, _e* buf, int_type len, int file = 0 ) 
	{ 
		return s ? s->send( _tmo, sa, buf, len, file ) : 0; 
	} 
	// returns the number of bytes read 
	int_type read( _e *buf, int_type len )  
	{  
		return recv( buf, len );  
	} 
	// returns the number of bytes written  
	int_type write( _e *buf, streamsize len )  
	{  
		return send( buf, len );  
	} 
 
	// set input and output buffer size (0 == none) 
	int_type setinputbuf( int_type sz ) 
	{  
		return s ? s->setinputbuf( sz ) : 0; 
	} 
	int_type setoutputbuf( int_type sz ) 
	{  
		return s ? s->setoutputbuf( sz ) : 0; 
	} 
	 
	// get input and output buffer size 
	int_type getinputbufsize() 
	{  
		return s ? s->isz : 0; 
	} 
	int_type getoutputbufsize() 
	{  
		return s ? s->osz : 0; 
	} 
	 
 
 
	// OBSERVER METHODS 
 
	// return peer address 
	bool peer( sockAddr &sa ) 
	{ 
		int len = sa.size(); 
		return s ? (::getpeername( s->sock, sa.addr(), &len ) != _Myt::invalid ) : false; 
	} 
 
	// return local address 
	bool local( sockAddr &sa ) 
	{ 
		int len = sa.size(); 
		return s ? (::getsockname( s->sock, sa.addr(), &len ) != _Myt::invalid ) : false; 
	} 
	 
	// return number of elements available 
	int_type in_avail() 
	{ 
		unsigned long n; 
		if( s && ::ioctlsocket( s->sock, FIONREAD, &n ) != _Myt::invalid )  
			return n; 
		else  
			return 0; 
	} 
 
	// OPTION SETTING 
	bool shutdown( _Myt::shuthow sh ){ 
		return s ? s->shutdown( sh ) : false;  
	} 
 
	bool _GetBufPtrs( _e** &ibeg, _e** &inext, streamsize* &icnt, _e** &obeg, _e** &onext, streamsize* &ocnt ) 
	{ 
		if( s ) 
		{ 
			ibeg = &s->ibeg; inext = &s->inext; icnt = &s->icnt; 
			obeg = &s->obeg; onext = &s->onext; ocnt = &s->ocnt; 
		} 
		return s != 0; 
	} 
 
	int getopt (int op, void* buf, int len, int level=sol_socket) const 
	{ 
		if( ::getsockopt (sd(), level, op, (char*)buf, &len) != SOCKET_ERROR )  
			return len; 
		return 0; 
	} 
 
	bool setopt (int op, void* buf, int len, int level=sol_socket) const 
	{ 
		return ::setsockopt (sd(), level, op, (char*) buf, len) != SOCKET_ERROR; 
	} 
 
	type gettype () const 
	{ 
		int ty=0; 
		if( getopt (so_type, &ty, sizeof (ty)) ) 
			return type(ty); 
		return type(invalid); 
	} 
 
	int clearerror () const 
	{ 
		int err=0; 
		if( getopt (so_error, &err, sizeof (err)) ) 
			return err; 
		return invalid; 
	} 
 
	bool debug () const 
	{ 
		int old = 0; 
		getopt (so_debug, &old, sizeof (old)); 
		return old==0; 
	} 
 
	bool debug (bool set) const 
	{ 
		int old=0; 
		int opt = set?1:0; 
		if( getopt (so_debug, &old, sizeof (old)) ) 
			setopt (so_debug, &opt, sizeof (opt)); 
		return old==0; 
	} 
 
	bool reuseaddr () const 
	{ 
		int old = 0; 
		getopt (so_reuseaddr, &old, sizeof (old)); 
		return old==0; 
	} 
 
	bool reuseaddr (bool set) const 
	{ 
		int old=0; 
		int opt = set?1:0; 
		getopt (so_reuseaddr, &old, sizeof (old)); 
		setopt (so_reuseaddr, &opt, sizeof (opt)); 
		return old==0; 
	} 
 
	bool keepalive () const 
	{ 
		int old = 0; 
		getopt (so_keepalive, &old, sizeof (old)); 
		return old==0; 
	} 
 
	bool keepalive (bool set) const 
	{ 
		int old=0; 
		int opt = set?1:0; 
		if( getopt (so_keepalive, &old, sizeof (old)) ) 
			setopt (so_keepalive, &opt, sizeof (opt)); 
		return old==0; 
	} 
 
	bool dontroute () const 
	{ 
		int old = 0; 
		getopt (so_dontroute, &old, sizeof (old)); 
		return old==0; 
	} 
 
	bool dontroute (bool set) const 
	{ 
		int old = 0; 
		int opt = set?1:0; 
		if( getopt (so_dontroute, &old, sizeof (old)) ) 
			setopt (so_dontroute, &opt, sizeof (opt)); 
		return old==0; 
	} 
 
	bool broadcast () const 
	{ 
		int old=0; 
		getopt (sobufroadcast, &old, sizeof (old)); 
		return old!=0; 
	} 
 
	bool broadcast (bool set) const 
	{ 
		int old = 0; 
		int opt = set?1:0; 
		if( getopt (sobufroadcast, &old, sizeof (old)) ) 
			setopt (sobufroadcast, &opt, sizeof (opt)); 
		return old!=0; 
	} 
 
	bool oobinline () const 
	{ 
		int old=0; 
		getopt (so_oobinline, &old, sizeof (old)); 
		return old==0; 
	} 
     
	bool oobinline (bool set) const 
	{ 
		int old = 0; 
		int opt = set?1:0; 
		if( getopt (so_oobinline, &old, sizeof (old)) ) 
			setopt (so_oobinline, &opt, sizeof (opt)); 
		return old==0; 
	} 
 
	bool oob (bool b) 
	{ 
		bool old = s->oob; 
		s->oob = b; 
		return old==0; 
	} 
 
	socklinger linger () const 
	{ 
		socklinger old (0, 0); 
		getopt (soleninger, &old, sizeof (old)); 
		return old; 
	} 
 
	socklinger linger (socklinger opt) const 
	{ 
		socklinger old (0, 0); 
		if( getopt (soleninger, &old, sizeof (old)) ) 
			setopt (soleninger, &opt, sizeof (opt)); 
		return old; 
	} 
 
	bool atmark () const 
	// return true, if the read pointer for socket points to an 
	// out of band data 
	{ 
		unsigned long arg; 
		if (::ioctlsocket (s->sock, SIOCATMARK, &arg) == SOCKET_ERROR) 
			false; 
		return arg!=0; 
	} 
 
	long nread () const 
	// return how many chars are available for reading in the recvbuf of 
	// the socket. 
	{ 
		unsigned long arg; 
		if (::ioctlsocket (s->sock, FIONREAD, &arg) == SOCKET_ERROR) 
			return 0; 
		return (long)arg; 
	} 
 
	bool nbio (bool set) const 
	// if set is true, set socket to non-blocking io. Henceforth, any 
	// write or read operation will not wait if write or read would block. 
	// The read or write operation will result throwing a sockerr 
	// exception with errno set to  EWOULDBLOCK. 
	{ 
		unsigned long  arg = set; 
		return ::ioctlsocket (s->sock, FIONBIO, &arg) != SOCKET_ERROR; 
	} 
 
 
 
protected: 
 
	struct streamTypeDef { 
		int family, type, protocol; 
	}; 
	streamTypeDef& getStreamType( socktype i ){ 
		static streamTypeDef streamTypeTbl[] = { 
			{invalid, 0,			0			}, 
			{AF_INET, SOCK_STREAM,	IPPROTO_TCP }, 
			{AF_INET, SOCK_DGRAM,	IPPROTO_UDP }, 
			{AF_INET, SOCK_RAW,		IPPROTO_ICMP}, 
			{AF_INET, SOCK_RAW,		IPPROTO_RAW }, 
			{AF_UNIX, SOCK_STREAM,	0			}, 
			{AF_UNIX, SOCK_DGRAM,	0			} 
		}; 
		if( i < _Myt::invalid_type || i >= sizeof(streamTypeTbl)/sizeof(streamTypeDef) ) 
			i = _Myt::invalid_type; 
		return streamTypeTbl[i]; 
	} 
 
	struct shared { 
		typedef shared _Myt; 
		typedef basic_socket myst; 
 
		SOCKET		sock;	// The shared socket 
		int			state;	// sock state (in,out,open, ...) 
		int			mode;	// open mode (in/out) 
		int			stmo;	// -1==block, 0==poll, >0 == waiting time in secs 
		int			rtmo;	// -1==block, 0==poll, >0 == waiting time in secs 
		int			refcnt;	// reference count 
		bool			oob;	// out of band flag 
		_e *ibeg, *obeg, *inext, *onext; 
		streamsize icnt, ocnt, isz,osz; // input and output buffer info 
 
		enum sockStates 
		{ 
			inopen	= ios::in, 
			outopen	= ios::out, 
			open	= ios::in|ios::out, 
		}; 
 
		shared( SOCKET s, ios::openmode m, bool c = false ) 
			: stmo(basic_socket::infinite), rtmo(basic_socket::infinite),  
			refcnt(1), mode(m) 
		{ 
			ibeg = obeg = inext = onext = 0; 
			state = icnt = ocnt = isz = osz = 0; 
			if( (sock=s) != basic_socket::invalid && c ) 
			{ 
				state |= mode & _Myt::open; 
				if( !(state&_Myt::inopen) ) 
					shutdown( basic_socket::shut_read ); // close not opened 
				if( !(state&_Myt::outopen) ) 
					shutdown( basic_socket::shut_write ); // close not opened 
			} 
		} 
		~shared() 
		{ 
			if( ibeg ) delete[] ibeg; 
			if( obeg ) delete[] obeg; 
			::closesocket( sock ); 
		} 
		// resize buffers to size. 
		int_type setinputbuf( streamsize sz ){ 
			if( sz == isz ) return isz; 
			if( sz == 0 || !(mode & ios::in) ) 
			{ 
				ibeg = new char[sz]; 
				ibeg = inext = 0; icnt = 0; isz = 0; 
				return true; 
			} 
			if( sz < icnt ) sz = icnt; 
			if( sz < basic_socket::minbsize ) sz = basic_socket::minbsize; 
			if( sz > basic_socket::maxbsize ) sz = basic_socket::maxbsize; 
			_e *_Ti = new char[sz];  
			if( _Ti == NULL ) return isz; 
			if( ibeg ) 
			{	 
				if( icnt ) memcpy( _Ti + sz - icnt, inext, icnt ); 
				delete[] ibeg; 
			}  
			inext = ibeg = _Ti; inext += sz - icnt; 
			return isz = sz; 
		} 
		// resize buffers to size. 
		int_type setoutputbuf( streamsize sz ){ 
			if( sz == osz ) return osz; 
			if( sz == 0 || !(mode & ios::out) ) 
			{ 
				obeg = new char[sz]; 
				obeg = onext = 0; ocnt = 0; osz = 0; 
				return true; 
			} 
			if( sz < onext-obeg ) sz = onext-obeg; 
			if( sz < basic_socket::minbsize ) sz = basic_socket::minbsize; 
			if( sz > basic_socket::maxbsize ) sz = basic_socket::maxbsize; 
			_e *_To =new char[sz]; 
			if( _To == NULL ) return osz; 
			if( obeg ) 
			{	 
				if( onext-obeg ) memcpy( _To, obeg, onext-obeg ); 
				delete[] obeg; 
			}  
			onext = obeg = _To; ocnt += sz - osz; onext += sz - ocnt;  
			return osz = sz; 
		} 
		bool shutdown( shuthow sh ){ 
			if( sh == basic_socket::shut_read || sh == basic_socket::shutbufoth ) 
			{ 
				setinputbuf( 0 ); 
				state &= ~_Myt::inopen; 
				mode &= ~ios::in; 
			} 
			if( sh == basic_socket::shut_write || sh == basic_socket::shutbufoth ) 
			{ 
				setoutputbuf( 0 ); 
				state &= ~_Myt::outopen; 
				mode &= ~ios::out; 
			} 
			return ::shutdown( sock, sh ) != basic_socket::invalid; 
		} 
		 
		bool is_readready( int ms, bool &_To ) 
		{ 
			int _R; 
			fd_set files; 
			FD_ZERO(&files); 
			FD_SET( sock, &files ); 
			if( ms == basic_socket::infinite ) 
				_R = ::select( sock+1, &files, 0, 0, 0 ); 
			else  
			{ 
				timeval _Tv; _Tv.tv_sec = ms/1000; _Tv.tv_usec = (ms*1000)%1000000; 
				_R = ::select( sock+1, &files, 0, 0, &_Tv ); 
			} 
			_To = (_R == 0); 
			return _R && (_R != basic_socket::invalid); 
		} 
		bool is_writeready( int ms, bool &_To )  
		{ 
			int _R; 
			fd_set files; 
			FD_ZERO(&files); 
			FD_SET( sock, &files ); 
			if( ms == basic_socket::infinite ) 
				_R = ::select( sock+1, 0, &files, 0, 0 ); 
			else  
			{ 
				timeval _Tv; _Tv.tv_sec = ms/1000; _Tv.tv_usec = (ms*1000)%1000000; 
				_R = ::select( sock+1, 0, &files, 0, &_Tv ); 
			} 
			_To = (_R == 0); 
			return _R && (_R != basic_socket::invalid); 
		} 
		bool is_exceptionpending( int ms, bool &_To ) 
		{ 
			int _R; 
			fd_set files; 
			FD_ZERO(&files); 
			FD_SET( sock, &files ); 
			if( ms == basic_socket::infinite ) 
				_R = ::select( sock+1, 0, 0, &files, 0 ); 
			else  
			{ 
				timeval _Tv; _Tv.tv_sec = ms/1000; _Tv.tv_usec = (ms*1000)%1000000; 
				_R = ::select( sock+1, 0, 0, &files, &_Tv ); 
			} 
			_To = (_R == 0); 
			return _R && (_R != basic_socket::invalid); 
		} 
		int_type recv( bool &_To, _e* buf, int_type len, int file = 0 ) 
		{ 
			int_type _R = 0;_To = false; 
			if( rtmo == basic_socket::infinite || is_readready( rtmo, _To ) ) 
			{ 
				_R = ::recv( sock, (char*)buf, len*sizeof(_e), file ); 
				if( _R == 0 ) state &= ~_Myt::open; 
				else if( _R == basic_socket::invalid ) _R = 0; 
			} 
			return _R/sizeof(_e); // drop partial char received  
		} 
		int_type recv( bool &_To, sockAddr &sa, _e* buf, int_type len, int file = 0 ) 
		{ 
			int_type _R = 0;_To = false; 
			if( rtmo == basic_socket::infinite || is_readready( rtmo, _To ) ) 
			{ 
				int lena = sa.size(); 
				_R = ::recvfrom( sock, (char*)buf, len*sizeof(_e), file, sa.addr(), &lena ); 
				if( _R == 0 ) state &= ~_Myt::open; 
				else if( _R == basic_socket::invalid ) _R = 0; 
			} 
			return _R/sizeof(_e); // drop partial char received  
		} 
		bool recvAll( bool &_To, _e* buf, int_type len, int file = 0 ) 
		{ 
			int_type _R = 0;_To = false; 
			char *p = (char*)buf; 
			len *= sizeof(_e); 
			while( len && !_To ) 
			{ 
				if( rtmo == basic_socket::infinite || is_readready( rtmo, _To ) ) 
				{ 
					_R = ::recv( sock, p, len, file ); 
					if( _R <= 0 ){state &= ~_Myt::open; return false; } 
					len -= _R; p += _R; 
				} 
			} 
			return !len && !_To; 
		} 
		int_type send( bool &_To, _e* buf, int_type len, int file = 0 ) 
		{ 
			int_type ns = 0; _To = false; 
			if( rtmo == basic_socket::infinite || is_writeready( rtmo, _To ) ) 
			{ 
				char *p = (char*)buf; 
				int_type n = len*sizeof(_e); 
				while( n ) 
				{ 
					int_type _R = ::send( sock, p,n*sizeof(_e), file ); 
					if( _R == 0 ) { state &= ~_Myt::open; break; } 
					if( _R == basic_socket::invalid ) break; 
					p += _R; ns += _R; n -= _R; 
				} 
			} 
			return ns/sizeof(_e); // drop partial char sent 
		} 
		int_type send( bool &_To, sockAddr &sa, _e* buf, int_type len, int file = 0 ) 
		{ 
			int_type ns = 0; _To = false; 
			if( rtmo == basic_socket::infinite || is_writeready( rtmo, _To ) ) 
			{ 
				char *p = (char*)buf; 
				int_type n = len*sizeof(_e); 
				while( n ) 
				{ 
					int lena = sa.size(); 
					int _R = ::sendto( sock, p, n, file, sa.addr(), sa.size() ); 
					if( _R == 0 ) { state &= ~_Myt::open; break; } 
					if( _R == basic_socket::invalid ) break; 
					p += _R; ns += _R; n -= _R; 
				} 
			} 
			return ns/sizeof(_e); // drop partial char sent 
		} 
		int sendtimeout( int msec ){ int t = stmo; stmo = msec; return t; } 
		int recvtimeout( int msec ){ int t = rtmo; rtmo = msec; return t; } 
	}; 
 
	 
shared * sharedSocket() const { return s; } 
private: 
	// LOCAL VARIABLES 
	shared *s;	// shared information 
	bool	_tmo;	// signals a time out event 
}; 
 
#ifdef WIN32 
#ifdef _DLL 
#pragma warning(disable:4231) /* the extern before template is a non-standard extension */ 
extern template class cRTIMP basic_socket >; 
extern template class cRTIMP basic_socket >; 
#pragma warning(default:4231) /* restore previous warning */ 
#else 
typedef basic_socket sock; 
#endif		// _DLL 
_STD_END 
#else 
typedef basic_socket sock; 
#endif //WIN32 
#ifdef  _MSC_VER 
#pragma pack(pop) 
#endif  /* mSC_VER */ 
 
#endif /* bufASIC_SOCKET_ */