// socket.cpp // Revision 24-apr-2009 #include "socket.h" #include //------------------------------------------------ // Changed this: now do not use winsock in Cygwin. //------------------------------------------------ //#if defined _Windows || defined __CYGWIN__ || defined __MINGW32__ // #if defined _Windows || defined __MINGW32__ #include typedef SOCKET TypeSocket; const TypeSocket InvalidSocket= INVALID_SOCKET; inline bool isInvalidSocket (TypeSocket s) { return s == INVALID_SOCKET; } namespace { class InitWinSock { InitWinSock () { WSADATA data; r= WSAStartup (0x0101, & data); } ~InitWinSock () { WSACleanup (); } int r; static InitWinSock init; struct avoid_ugly_warning { }; friend struct avoid_ugly_warning; }; InitWinSock InitWinSock::init; } // namespace #else #include #include #include #include #include #include typedef int TypeSocket; const TypeSocket InvalidSocket= -1; inline bool isInvalidSocket (TypeSocket s) { return s < 0; } inline int closesocket (int handle) { return close (handle); } #endif #include #ifdef __BORLANDC__ #pragma warn -inl #endif //********************************************************** // SocketError //********************************************************** std::string SocketError::strErr= "Socket error in "; SocketError::SocketError (const std::string & nstr) { str= strErr; str+= nstr; } SocketError::SocketError (const std::string & nstr, int errnum) { str= strErr; str+= nstr; str+= ": "; str+= strerror (errnum); } const char * SocketError::what () const throw () { return str.c_str (); } //********************************************************** // Socket::Internal //********************************************************** class Socket::Internal { public: Internal () : refcount (1), s (InvalidSocket), maxbuf (0), posbuf (0) { } void addref () { ++refcount; } void delref () { if (--refcount == 0) { if (! isInvalidSocket (s) ) closesocket (s); delete this; } } void set (TypeSocket ns) { s= ns; } TypeSocket handle () { return s; } int connect (sockaddr * name, int namelen) { //if (! isInvalidSocket (s) ) // throw SocketError ("connect: already connected"); return ::connect (s, name, namelen); } bool eof () { if (posbuf < maxbuf) return false; getbuffer (); return maxbuf == 0; } int recv (char * bufrec, size_t len, int flags= 0); int send (const char * buffer, size_t len, int flags= 0) { return ::send (s, buffer, len, flags); } char get () { if (posbuf >= maxbuf) { getbuffer (); if (maxbuf == 0) return 0; } return buffer [posbuf++]; } private: size_t refcount; TypeSocket s; static const size_t bufsiz= 1024; char buffer [bufsiz]; size_t maxbuf, posbuf; void getbuffer () { posbuf= 0; maxbuf= 0; int i= ::recv (s, buffer, bufsiz, 0); if (i > 0) maxbuf= i; } }; int Socket::Internal::recv (char * bufrec, size_t len, int flags) { if (posbuf < maxbuf) { size_t send= maxbuf - posbuf; if (len < send) send= len; for (size_t i= 0, j= posbuf; i < send; ++i, ++j) bufrec [i]= buffer [j]; posbuf+= send; return send; } return ::recv (s, bufrec, len, flags); } //********************************************************** // Socket //********************************************************** Socket::Socket () { in= new Internal; } Socket::Socket (const Socket & nsock) { in= nsock.in; in->addref (); } Socket::~Socket () { in->delref (); } Socket & Socket::operator = (const Socket & nsock) { Internal * nin; nin= nsock.in; nin->addref (); in->delref (); in= nin; return * this; } #if 0 TypeSocket Socket::handle () { return in->handle (); } #endif bool Socket::eof () { return in->eof (); } std::string Socket::readline () { char c; std::string str; while ( (c= in->get () ) != '\n' && c != '\0') str+= c; #if 0 std::string::size_type l= str.size (); if (l > 0 && str [l - 1] == '\r') str.erase (l - 1); #endif return str; } int Socket::read (char * str, int len) { return in->recv (str, len); } void Socket::write (const std::string & str) { in->send (str.data (), str.size () ); } void Socket::write (const char * str, size_t len) { in->send (str, len); } //********************************************************** // TcpSocket //********************************************************** TcpSocket::TcpSocket () { protoent * pe= getprotobyname ("tcp"); int proto= pe ? pe->p_proto : 0; TypeSocket s= socket (PF_INET, SOCK_STREAM, proto); in->set (s); } //********************************************************** // TcpSocketClient //********************************************************** TcpSocketClient::TcpSocketClient (const std::string & host, unsigned short port) { hostent * hent= gethostbyname (host.c_str () ); if (! hent) throw SocketError (std::string ("search from host ") + host, errno); sockaddr_in addr; addr.sin_family= AF_INET; addr.sin_port= htons (port); addr.sin_addr= * (in_addr *) hent->h_addr_list [0]; if (in->connect ( (sockaddr *) & addr, sizeof (addr) ) != 0) throw SocketError (std::string ("connect with ") + host, errno); } // Fin de socket.cpp