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

📄 socket.h

📁 一个unix和windows通用的socket函数封装的类
💻 H
📖 第 1 页 / 共 2 页
字号:
/************************************************************************************
*                                                                                   *
*    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 <new>

// OS Specific includes
#ifdef WIN32
	#include <iostream>
	#include <windows.h>
	#include <sys/types.h>

#else
	#define BSD_COMP

	#include <sys/uio.h>
	#include <sys/ioctl.h>
	#include <sys/socket.h>
    #include <sys/time.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>

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

⌨️ 快捷键说明

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