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

📄 socket.h

📁 一个unix和windows通用的socket函数封装的类
💻 H
📖 第 1 页 / 共 2 页
字号:
	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<char, char_traits<char> >;
extern template class cRTIMP basic_socket<wchar_t, char_traits<wchar_t> >;
#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_ */

⌨️ 快捷键说明

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