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_ */