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

📄 tcpsocket.cpp

📁 一个简单实用的开源C++消息中间件SAFMQ - [软件开发] - [开源 消息中间件 SAFMQ ] 2006-11-23 在很多网络应用中
💻 CPP
📖 第 1 页 / 共 2 页
字号:
{
	tcpsocket::sleep(milliseconds);
}

// /////////////////////////////////////////////////////////////////////////////
// BufferedSocket Implementation
// /////////////////////////////////////////////////////////////////////////////

void BufferedSocket::init(int bufSize)
{
	if (bufSize > 0) {
		m_bufSize = bufSize;
		m_inBuffer = new char[bufSize];
		m_outBuffer = new char[bufSize];
	} else if (bufSize < 0) {
		if (m_socket != 0) {
			int	rcvs;
			int snds;
			socklen_t	ilen;
			ilen = sizeof(rcvs);
			::getsockopt(m_socket->getSocket(),SOL_SOCKET,SO_RCVBUF,(char*)&rcvs,&ilen);
			ilen = sizeof(snds);
			::getsockopt(m_socket->getSocket(),SOL_SOCKET,SO_SNDBUF,(char*)&snds,&ilen);


			m_bufSize = std::min(rcvs,snds);
			m_inBuffer = new char[m_bufSize];
			m_outBuffer = new char[m_bufSize];
		}
	} else {
		throw std::bad_alloc();
	}
	m_inPos = 0;
	
	m_outPos = m_outEnd = 0xFFFFFFFF;
}

/**
Destroys the buffered socket object.
*/
BufferedSocket::~BufferedSocket()
{
	delete [] m_inBuffer;
	delete [] m_outBuffer;
	if (m_allocsocket)
		delete m_socket;
}

/**
Sends data over the socket.  Sends exactly <code>length</code> bytes.

@param sendBuffer [in] A buffer containing the data to be sent
@param length [in] The number of bytes in the buffer
@return The number of bytes sent, -1 on error, and 0 if the connection was closed
@exception SocketException if the connection was closed and the throw on close flag was set.
*/
size_t BufferedSocket::send(const char* sendBuffer, size_t length)	throw (SocketException)
{
	int	olength = (int)length;
	while (length > 0) {
		if (m_inPos+length <= m_bufSize) {
			::memcpy(m_inBuffer+m_inPos,sendBuffer,length);
			m_inPos += length;
			length = 0;
			if (m_inPos == m_bufSize) // don't delay the send if it's not necessary
				flush();
		} else { 
			::memcpy(m_inBuffer+m_inPos,sendBuffer,m_bufSize-m_inPos);
			sendBuffer += m_bufSize-m_inPos;
			length -= m_bufSize-m_inPos;
			m_inPos = m_bufSize;
			flush();
		}
	}
	return olength;
}

/**
Receives data from the socket.  Receives exactly <code>length</code> bytes or
less if the socket is closed early.

@param sendBuffer [out] A buffer receiving the data 
@param length [in] The maximum number of bytes in the buffer
@return The number of bytes received, -1 on error, and 0 if the connection was closed
@exception SocketException if the connection was closed and the throw on close flag was set.
*/
size_t BufferedSocket::receive(char* readBuffer, size_t length)		throw (SocketException)
{
	int	olength = (int)length;
	
	while (m_outEnd && length > 0) {
		if (length <= m_outEnd-m_outPos) {
			::memcpy(readBuffer, m_outBuffer+m_outPos, length);
			m_outPos += length;
			length = 0;
		} else {
			if (m_outEnd != m_outPos)
				::memcpy(readBuffer, m_outBuffer+m_outPos, m_outEnd-m_outPos);
			length -= m_outEnd-m_outPos;
			readBuffer += m_outEnd-m_outPos;
			underflow();
		}
	}
	if (length)
		return olength - length;

	return olength;
}

/**
Receives data from the socket.  Receives upto <code>length</code> bytes.

@param sendBuffer [out] A buffer receiving the data 
@param length [in] The maximum number of bytes in the buffer
@return The number of bytes received, -1 on error, and 0 if the connection was closed
@exception SocketException if the connection was closed and the throw on close flag was set.
*/
size_t BufferedSocket::receiveSome(char* readBuffer, size_t length)	throw (SocketException)
{
	int	olength = (int)length;
	while (m_outEnd && length == olength) {
		if (length <= m_outEnd-m_outPos) {
			::memcpy(readBuffer, m_outBuffer+m_outPos, length);
			m_outPos += length;
			length = 0;
		} else {
			if (m_outEnd != m_outPos)
				::memcpy(readBuffer, m_outBuffer+m_outPos, m_outEnd-m_outPos);
			length -= m_outEnd-m_outPos;
			underflow();
		}
	}
	return olength - length;
}

/**
Reads a single character from the stream
@return -1 in case the stream is closed
@throw SocketException
*/
int BufferedSocket::get() throw (SocketException)
{
	unsigned char	c;
	size_t	i = receive((char*)&c,sizeof(c));
	if (i != sizeof(c))
		return -1;
	return (int)c;
}

/**
Looks at the buffer and returns the first byte in the buffer.
@return The first byte in teh buffer or -1 on error
*/
int BufferedSocket::peek() throw (SocketException)
{
	if (m_outPos == m_outEnd) underflow();
	if (m_outPos < m_outEnd)
		return (int)(((unsigned char*)m_outBuffer)[m_outPos]);
	return -1;
}
/**
Places a character back into the buffer
@return -1 on error
*/
int BufferedSocket::putback(int c) throw (SocketException)
{
	if (m_outPos > 0) {
		if (c == -1) {
			m_outPos--;
		} else {
			m_outPos--;
			((unsigned char*)m_outBuffer)[m_outPos] = (unsigned char)(c & 0x00FF);
		}
		return (int)(((unsigned char*)m_outBuffer)[m_outPos]);
	}
	return -1;
}

/**
Reads until the end of the line has been read
@throw SocketException
*/
void BufferedSocket::getLine(std::string& line, const std::string& eol) throw (SocketException)
{
	int	c;
	line.erase(line.begin(),line.end());
	while ( line.length() < eol.length() || line.substr(line.length()-eol.length()) != eol) {
		try {
			c = get();
		
			if (c >= 0)
				line.append(1,(char)c);
			else if (m_throwOnClose) {
				throw SocketException(ECONNRESET);
			} else
				break;
		} catch (SocketException e) {
			if (line.length() == 0)
				throw;
			break;
		}
	}
	if ( line.length() >= eol.length() && line.substr(line.length()-eol.length()) == eol)
		line.erase(line.length()-eol.length());
}

/**
Flushes the write buffer over the socket connection.
@return the number of bytes sent, 0 if the socket was closed, or -1 on an error
@exception Throws SocketException if the socket was closed and the throw on close flag was set.
*/
int BufferedSocket::flush() throw (SocketException)
{
	int sent = (int)m_socket->send(m_inBuffer,m_inPos);
	if (sent > 0)
		m_inPos = 0;
	else {
		int err = SOCERRNO;
		return sent;
	}
	return sent;
}

/**
Writes a string to the buffered socket.
@param str The string to write to the buffered socket
@return A reference to this buffered socket
*/
BufferedSocket& BufferedSocket::operator << (const std::string& str) throw (SocketException)
{
	send(str.c_str(),str.length());
	return *this;
}

/**
Calls a stream format function like endl or flush to operate against this socket.
@param str The string to write to the buffered socket
@return A reference to this buffered socket
*/
BufferedSocket& BufferedSocket::operator << (BufferedSocket& (*sockFunc)(BufferedSocket*) throw (SocketException)) throw (SocketException)
{
	return sockFunc(this);
}

void BufferedSocket::underflow() throw (SocketException)
{
	m_outPos = 0;
	m_outEnd = 0; // set just incase Socket::receiveSome throws an exception
	m_outEnd = m_socket->receiveSome(m_outBuffer,m_bufSize);
}

/**
Flushes and closes the socket.
*/
void BufferedSocket::close() throw (SocketException)
{
	flush();
	m_socket->close();
}

BufferedSocket& endl(BufferedSocket* s) throw (SocketException)
{
	s->send("\n",1);
	s->flush();
	return *s;
}

BufferedSocket& flush(BufferedSocket* s) throw (SocketException)
{
	s->flush();
	return *s;	
}

// /////////////////////////////////////////////////////////////////////////////
// ServerSocket Implementation
// /////////////////////////////////////////////////////////////////////////////
/**
Constructs the server socket binding to the port and optionally using the bind address and listener backlog
@param bindPort [in] The TCP port to bind to
@param bindAddress [in,optional] Optional address to bind to, if not specified all local address
									will be bound.
@param listenerBacklog [in,optional] Optional depth of the listener queue.
@throw SocketException on an error
*/
ServerSocket::ServerSocket(short bindPort, unsigned long bindAddress, int listenerBacklog) throw (SocketException)
{
	struct sockaddr_in	saddr;

	m_socket = (int)::socket(AF_INET, SOCK_STREAM, 0);

	memset(&saddr, 0, sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(bindPort);
	saddr.sin_addr	= *(struct in_addr*)&bindAddress;

	int	iReuse = 1;
	::setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (const char*) &iReuse, sizeof(int));

	if (::bind(m_socket, (struct sockaddr*)&saddr, sizeof(saddr)) != 0) {
		int err = SOCERRNO;
		close();
		throw SocketException(err);
	}

	if (::listen(m_socket, listenerBacklog) != 0) {
		int err = SOCERRNO;
		close();
		throw SocketException(err);
	}
}

/**
Releases the server socket
@throw SocketException on an error
*/
ServerSocket::~ServerSocket() throw (SocketException)
{
	close();
}

/**
Accepts a connection from the server socket.
@return A socket connected to a client
@throw SocketException on an error
*/
Socket ServerSocket::acceptConnection() throw (SocketException)
{
	int	soc = (int)::accept(m_socket,NULL,NULL);
	if (soc < 0)
		throw SocketException(SOCERRNO);
	return Socket(soc);
}

} // end of namespace tcpsocket

⌨️ 快捷键说明

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