diff options
Diffstat (limited to 'socket.cpp')
-rw-r--r-- | socket.cpp | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/socket.cpp b/socket.cpp new file mode 100644 index 0000000..7d5bc71 --- /dev/null +++ b/socket.cpp @@ -0,0 +1,272 @@ +// socket.cpp +// Revision 24-apr-2009 + +#include "socket.h" + +#include <string.h> + +//------------------------------------------------ +// Changed this: now do not use winsock in Cygwin. +//------------------------------------------------ +//#if defined _Windows || defined __CYGWIN__ || defined __MINGW32__ +// +#if defined _Windows || defined __MINGW32__ + +#include <winsock.h> + +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 <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> + +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 <errno.h> + +#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 |