text: #include "Socket.h"
  #include <iostream>
  
  using namespace std;
  
  int Socket::nofSockets_= 0;
  
  #define WSA_INIT
  
  void Socket::Start()
  {
  	if (!nofSockets_) 
  	{
  #ifndef WSA_INIT
  		WSADATA info;
  		if (WSAStartup(MAKEWORD(2, 2), &info))
  		{
  			throw "Could not start WSA";
  		}
  #endif
  	}
  	++nofSockets_;
  }
  
  void Socket::End() 
  {
  #ifndef WSA_INIT
  	WSACleanup();
  #endif
  }
  
  Socket::Socket() : s_(0) {
  	Start();
  	// UDP: use SOCK_DGRAM instead of SOCK_STREAM
  	s_ = socket(AF_INET, SOCK_STREAM, 0);
  
  	if (s_ == INVALID_SOCKET) {
  		throw "INVALID_SOCKET";
  	}
  
  	refCounter_ = new int(1);
  }
  
  Socket::Socket(SOCKET s) : s_(s) 
  {
  	Start();
  	refCounter_ = new int(1);
  };
  
  Socket::~Socket() {
  	if (! --(*refCounter_))
  	{
  		Close();
  		delete refCounter_;
  	}
  
  	--nofSockets_;
  	if (!nofSockets_) End();
  }
  
  Socket::Socket(const Socket& o) {
  	refCounter_=o.refCounter_;
  	(*refCounter_)++;
  	s_         =o.s_;
  
  	nofSockets_++;
  }
  
  Socket& Socket::operator=(Socket& o) {
  	(*o.refCounter_)++;
  
  	refCounter_=o.refCounter_;
  	s_         =o.s_;
  
  	nofSockets_++;
  
  	return *this;
  }
  
  void Socket::Close() {
  	closesocket(s_);
  }
  
  std::string Socket::ReceiveBytes() {
  	std::string ret;
  	char buf[1024];
  
  	while (1) {
  		u_long arg = 0;
  		if (ioctlsocket(s_, FIONREAD, &arg) != 0)
  			break;
  
  		if (arg == 0)
  			break;
  
  		if (arg > 1024) arg = 1024;
  
  		int rv = recv (s_, buf, arg, 0);
  		if (rv <= 0) break;
  
  		std::string t;
  
  		t.assign (buf, rv);
  		ret += t;
  	}
  
  	return ret;
  }
  
  std::string Socket::ReceiveLine() {
  	std::string ret;
  	while (1) {
  		char r;
  
  		switch(recv(s_, &r, 1, 0)) {
  	  case 0: // not connected anymore;
  		  // ... but last line sent
  		  // might not end in \n,
  		  // so return ret anyway.
  		  return ret;
  	  case -1:
  		  return "";
  		  //      if (errno == EAGAIN) {
  		  //        return ret;
  		  //      } else {
  		  //      // not connected anymore
  		  //      return "";
  		  //      }
  		}
  
  		ret += r;
  		if (r == '\n')  return ret;
  	}
  }
  
  void Socket::SendLine(std::string s) {
  	s += '\n';
  	send(s_,s.c_str(),s.length(),0);
  }
  
  void Socket::SendBytes(const std::string& s) {
  	send(s_,s.c_str(),s.length(),0);
  }
  
  SocketServer::SocketServer(int port, int connections, TypeSocket type) {
  	sockaddr_in sa;
  
  	memset(&sa, 0, sizeof(sa));
  
  	sa.sin_family = PF_INET;             
  	sa.sin_port = htons(port);          
  	s_ = socket(AF_INET, SOCK_STREAM, 0);
  	if (s_ == INVALID_SOCKET) {
  		throw "INVALID_SOCKET";
  	}
  
  	if(type==NonBlockingSocket) {
  		u_long arg = 1;
  		ioctlsocket(s_, FIONBIO, &arg);
  	}
  
  	/* bind the socket to the internet address */
  	if (bind(s_, (sockaddr *)&sa, sizeof(sockaddr_in)) == SOCKET_ERROR) {
  		closesocket(s_);
  		throw "INVALID_SOCKET";
  	}
  
  	listen(s_, connections);                               
  }
  
  Socket* SocketServer::Accept() {
  	SOCKET new_sock = accept(s_, 0, 0);
  	if (new_sock == INVALID_SOCKET) {
  		int rc = WSAGetLastError();
  		if(rc==WSAEWOULDBLOCK) {
  			return 0; // non-blocking call, no request pending
  		}
  		else {
  			throw "Invalid Socket";
  		}
  	}
  
  	Socket* r = new Socket(new_sock);
  	return r;
  }
  
  SocketClient::SocketClient(const std::string& host, int port) : Socket() {
  	std::string error;
  
  	hostent *he;
  	if ((he = gethostbyname(host.c_str())) == 0) {
  		error = strerror(errno);
  		throw error;
  	}
  
  	sockaddr_in addr;
  	addr.sin_family = AF_INET;
  	addr.sin_port = htons(port);
  	addr.sin_addr = *((in_addr *)he->h_addr);
  	memset(&(addr.sin_zero), 0, 8); 
  
  	if (::connect(s_, (sockaddr *) &addr, sizeof(sockaddr))) {
  		error = strerror(WSAGetLastError());
  		throw error;
  	}
  }
  
  SocketSelect::SocketSelect(Socket const * const s1, Socket const * const s2, TypeSocket type) {
  	FD_ZERO(&fds_);
  	FD_SET(const_cast<Socket*>(s1)->s_,&fds_);
  	if(s2) {
  		FD_SET(const_cast<Socket*>(s2)->s_,&fds_);
  	}     
  
  	TIMEVAL tval;
  	tval.tv_sec  = 0;
  	tval.tv_usec = 1;
  
  	TIMEVAL *ptval;
  	if(type==NonBlockingSocket) {
  		ptval = &tval;
  	}
  	else { 
  		ptval = 0;
  	}
  
  	if (select (0, &fds_, (fd_set*) 0, (fd_set*) 0, ptval) == SOCKET_ERROR) 
  		throw "Error in select";
  }
  
  bool SocketSelect::Readable(Socket const* const s) {
  	if (FD_ISSET(s->s_,&fds_)) return true;
  	return false;
  }
  