363 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			363 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
#include "stdafx.h"
 | 
						|
#include "msocketx.h"
 | 
						|
 | 
						|
#ifdef _WIN32
 | 
						|
#pragma warning(disable:4244)
 | 
						|
#endif
 | 
						|
 | 
						|
msocketx::msocketx()
 | 
						|
{
 | 
						|
	m_sock = INVALID_SOCKET;
 | 
						|
}
 | 
						|
 | 
						|
msocketx::~msocketx()
 | 
						|
{
 | 
						|
	close();
 | 
						|
}
 | 
						|
int msocketx::getsockname(unsigned int& uiip, unsigned short& usport)
 | 
						|
{
 | 
						|
	sockaddr_in addr;
 | 
						|
	socklen_t ilen = sizeof(addr);
 | 
						|
 | 
						|
	int nret = ::getsockname(m_sock, (sockaddr*)&addr, &ilen);
 | 
						|
	if (nret != SOCKET_ERROR)
 | 
						|
	{
 | 
						|
		uiip = addr.sin_addr.s_addr;
 | 
						|
		usport = ntohs(addr.sin_port);
 | 
						|
	}
 | 
						|
 | 
						|
	return nret;
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::shutdown(int ihow)
 | 
						|
{
 | 
						|
	return ::shutdown(m_sock, ihow);
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::closesocket()
 | 
						|
{
 | 
						|
#ifdef _WIN32
 | 
						|
	return ::closesocket(m_sock);
 | 
						|
#else
 | 
						|
	return ::close(m_sock);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void msocketx::close()
 | 
						|
{
 | 
						|
	if (isvalid())
 | 
						|
	{
 | 
						|
		shutdown(0);
 | 
						|
		closesocket();
 | 
						|
		m_sock = INVALID_SOCKET;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::startup()
 | 
						|
{
 | 
						|
#ifdef _WIN32
 | 
						|
	WSADATA wsaData;
 | 
						|
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
 | 
						|
		return false;
 | 
						|
#endif
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::clearup()
 | 
						|
{
 | 
						|
#ifdef _WIN32
 | 
						|
	return WSACleanup() == 0;
 | 
						|
#endif
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::getlasterror()
 | 
						|
{
 | 
						|
#ifdef _WIN32
 | 
						|
	return WSAGetLastError();
 | 
						|
#else
 | 
						|
	return errno;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void msocketx::attach(SOCKET sock)
 | 
						|
{
 | 
						|
	if (sock == INVALID_SOCKET)
 | 
						|
		return;
 | 
						|
	m_sock = sock;
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::isvalid()
 | 
						|
{
 | 
						|
	return m_sock != INVALID_SOCKET;
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::setsockbuff(unsigned int uirecvlen /* = 4 * 1024 * 1024 */,
 | 
						|
	unsigned int uisendlen /* = 4 * 1024 * 1024 */)
 | 
						|
{
 | 
						|
	return (setsockopt(m_sock, SOL_SOCKET, SO_SNDBUF, (char*)&uisendlen, sizeof(uisendlen)) == 0) &&
 | 
						|
		(setsockopt(m_sock, SOL_SOCKET, SO_RCVBUF, (char*)&uirecvlen, sizeof(uirecvlen)) == 0);
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::setsocknagle(bool benable /* = true */)
 | 
						|
{
 | 
						|
	socklen_t iflag = (benable ? 0 : 1);
 | 
						|
	return setsockopt(m_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&iflag, sizeof(iflag)) == 0;
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::setsocktime(unsigned int uimillisecond /* = 500 */)
 | 
						|
{
 | 
						|
#ifdef _WIN32
 | 
						|
	return (setsockopt(m_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&uimillisecond, sizeof(uimillisecond)) == 0) &&
 | 
						|
		(setsockopt(m_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&uimillisecond, sizeof(uimillisecond)) == 0);
 | 
						|
#else
 | 
						|
	struct timeval timeout;
 | 
						|
	timeout.tv_sec = uimillisecond / 1000;
 | 
						|
	timeout.tv_usec = (uimillisecond % 1000) * 1000;
 | 
						|
	return (setsockopt(m_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)) == 0) &&
 | 
						|
		(setsockopt(m_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) == 0);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::setsock()
 | 
						|
{
 | 
						|
	return setsockbuff() && setsocktime();
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::setblock(bool bblock /* = false */)
 | 
						|
{
 | 
						|
#ifdef _WIN32
 | 
						|
	u_long b = bblock ? 0 : 1;
 | 
						|
	return ioctlsocket(m_sock, FIONBIO, &b) == 0;
 | 
						|
#else
 | 
						|
	int flags = fcntl(m_sock, F_GETFL, 0);
 | 
						|
	if (bblock)
 | 
						|
		flags |= O_NONBLOCK;
 | 
						|
	else
 | 
						|
		flags &= (~O_NONBLOCK);
 | 
						|
	return fcntl(m_sock, F_SETFL, flags) != -1;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::create(int itype, int iprotocol)
 | 
						|
{
 | 
						|
	if (isvalid())
 | 
						|
		return true;
 | 
						|
	m_sock = socket(AF_INET, itype, iprotocol);
 | 
						|
 | 
						|
	return isvalid();
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::bind(unsigned short usport, const char* pstrip /* = NULL */)
 | 
						|
{
 | 
						|
	sockaddr_in addr = { 0 };
 | 
						|
	unsigned long nResult = 0;
 | 
						|
 | 
						|
	addr.sin_family = AF_INET;
 | 
						|
 | 
						|
	if (pstrip == NULL)
 | 
						|
		addr.sin_addr.s_addr = htonl(INADDR_ANY);
 | 
						|
	else
 | 
						|
	{
 | 
						|
		nResult = inet_addr(pstrip);
 | 
						|
		if (nResult == INADDR_NONE)
 | 
						|
			return false;
 | 
						|
 | 
						|
		addr.sin_addr.s_addr = nResult;
 | 
						|
	}
 | 
						|
	addr.sin_port = htons(usport);
 | 
						|
 | 
						|
	return ::bind(m_sock, (sockaddr*)&addr, sizeof(addr)) == 0;
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::sendto(const void* pbuf, unsigned int ilen, unsigned int uiip, unsigned short usport, int iflags)
 | 
						|
{
 | 
						|
	if (pbuf == NULL)
 | 
						|
		return -1;
 | 
						|
 | 
						|
	sockaddr_in addr = { 0 };
 | 
						|
 | 
						|
	addr.sin_family = AF_INET;
 | 
						|
	addr.sin_addr.s_addr = uiip;
 | 
						|
	addr.sin_port = htons(usport);
 | 
						|
 | 
						|
	return ::sendto(m_sock, (char*)pbuf, ilen, iflags, (sockaddr*)&addr, sizeof(addr));
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::sendto(const void* pbuf, unsigned int ilen, const char* pszip, unsigned short usport, int iflags)
 | 
						|
{
 | 
						|
	if (pbuf == NULL)
 | 
						|
		return -1;
 | 
						|
	return sendto(pbuf, ilen, inet_addr(pszip), usport, iflags);
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::recvfrom(void* pbuf, unsigned int ilen, unsigned int& uiip, unsigned short& usport, int iflags)
 | 
						|
{
 | 
						|
	if (pbuf == NULL)
 | 
						|
		return -1;
 | 
						|
 | 
						|
	sockaddr_in srcaddr = { 0 };
 | 
						|
	socklen_t iaddrlen = sizeof(srcaddr);
 | 
						|
 | 
						|
	int nret = ::recvfrom(m_sock, (char*)pbuf, ilen, iflags, (sockaddr*)&srcaddr, &iaddrlen);
 | 
						|
	if (nret != SOCKET_ERROR)
 | 
						|
	{
 | 
						|
		usport = htons(srcaddr.sin_port);
 | 
						|
		uiip = srcaddr.sin_addr.s_addr;
 | 
						|
	}
 | 
						|
	return nret;
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::send(const void* pbuf, unsigned int ilen, int iflags)
 | 
						|
{
 | 
						|
	if (pbuf == NULL)
 | 
						|
		return -1;
 | 
						|
 | 
						|
	return ::send(m_sock, (char*)pbuf, ilen, iflags);
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::recv(void* pbuf, unsigned int ilen, int iflags)
 | 
						|
{
 | 
						|
	if (pbuf == NULL)
 | 
						|
		return -1;
 | 
						|
 | 
						|
	return ::recv(m_sock, (char*)pbuf, ilen, iflags);
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::listen(int ibacklog)
 | 
						|
{
 | 
						|
	return ::listen(m_sock, ibacklog) == 0;
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::accept(SOCKET& sock, sockaddr* peeraddr, socklen_t* addrlen)
 | 
						|
{
 | 
						|
	sock = ::accept(m_sock, peeraddr, addrlen);
 | 
						|
	return sock != INVALID_SOCKET;
 | 
						|
}
 | 
						|
 | 
						|
bool msocketx::accept(msocketx& sock, sockaddr* peeraddr, socklen_t* addrlen)
 | 
						|
{
 | 
						|
	SOCKET socktmp = ::accept(m_sock, peeraddr, addrlen);
 | 
						|
	sock.m_sock = socktmp;
 | 
						|
	return socktmp != INVALID_SOCKET;
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::connect(const char* pszip, unsigned short usport, bool bblock)
 | 
						|
{
 | 
						|
	if (pszip == NULL)
 | 
						|
		return -1;
 | 
						|
 | 
						|
	if (!isvalid())
 | 
						|
	{
 | 
						|
		if (!create(SOCK_STREAM, 0))
 | 
						|
			return -1;
 | 
						|
	}
 | 
						|
	setblock(bblock);
 | 
						|
 | 
						|
	sockaddr_in addr = { 0 };
 | 
						|
 | 
						|
	addr.sin_port = htons(usport);
 | 
						|
	addr.sin_addr.s_addr = inet_addr(pszip);
 | 
						|
	addr.sin_family = AF_INET;
 | 
						|
 | 
						|
	return ::connect(m_sock, (sockaddr*)&addr, sizeof(addr));
 | 
						|
}
 | 
						|
 | 
						|
int msocketx::wait(unsigned int uimilli, int iflagx)
 | 
						|
{
 | 
						|
	timeval timeout;
 | 
						|
	timeout.tv_sec = uimilli / 1000;
 | 
						|
	timeout.tv_usec = (uimilli % 1000) * 1000;
 | 
						|
 | 
						|
	fd_set *prfds = NULL, *pwfds = NULL, *pefds = NULL;
 | 
						|
	int iret = 0;
 | 
						|
 | 
						|
	if ((iflagx & CAN_CONNECTX) == CAN_CONNECTX)
 | 
						|
	{
 | 
						|
		pwfds = new(std::nothrow) fd_set;
 | 
						|
		if (pwfds == NULL)
 | 
						|
			return -1;
 | 
						|
 | 
						|
		pefds = new(std::nothrow) fd_set;
 | 
						|
		if (pefds == NULL)
 | 
						|
		{
 | 
						|
			if (pwfds)
 | 
						|
				delete pwfds;
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		FD_ZERO(pwfds);
 | 
						|
		FD_ZERO(pefds);
 | 
						|
 | 
						|
		FD_SET(m_sock, pwfds);
 | 
						|
		FD_SET(m_sock, pefds);
 | 
						|
 | 
						|
		iret = ::select(m_sock + 1, NULL, pwfds, pefds, &timeout);
 | 
						|
		if (iret > 0)
 | 
						|
		{
 | 
						|
			if (FD_ISSET(m_sock, pwfds) || FD_ISSET(m_sock, pefds))
 | 
						|
			{
 | 
						|
				int iopt = 0;
 | 
						|
				socklen_t ioptlen = sizeof(iopt);
 | 
						|
				if (getsockopt(m_sock, SOL_SOCKET, SO_ERROR, (char*)&iopt, &ioptlen) == 0)
 | 
						|
				{
 | 
						|
					if (iopt == 0)
 | 
						|
						iret = CAN_CONNECTX;
 | 
						|
					else
 | 
						|
						iret = SOCKET_ERROR;
 | 
						|
				}
 | 
						|
				else
 | 
						|
					iret = SOCKET_ERROR;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (pwfds)
 | 
						|
			delete pwfds;
 | 
						|
		if (pefds)
 | 
						|
			delete pefds;
 | 
						|
		return iret;
 | 
						|
	}
 | 
						|
 | 
						|
	if ((iflagx & CAN_READX) == CAN_READX || (iflagx & CAN_ACCEPTX) == CAN_ACCEPTX)
 | 
						|
	{
 | 
						|
		prfds = new(std::nothrow) fd_set;
 | 
						|
		if (prfds == NULL)
 | 
						|
			return -1;
 | 
						|
 | 
						|
		FD_ZERO(prfds);
 | 
						|
		FD_SET(m_sock, prfds);
 | 
						|
	}
 | 
						|
	if ((iflagx & CAN_WRITEX) == CAN_WRITEX)
 | 
						|
	{
 | 
						|
		pwfds = new(std::nothrow) fd_set;
 | 
						|
		if (pwfds == NULL)
 | 
						|
		{
 | 
						|
			if (prfds)
 | 
						|
				delete prfds;
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		FD_ZERO(pwfds);
 | 
						|
		FD_SET(m_sock, pwfds);
 | 
						|
	}
 | 
						|
 | 
						|
	iret = ::select(m_sock + 1, prfds, pwfds, NULL, &timeout);
 | 
						|
	if (iret > 0)
 | 
						|
	{
 | 
						|
		int itmp = 0;
 | 
						|
		if (prfds)
 | 
						|
			if (FD_ISSET(m_sock, prfds))
 | 
						|
				itmp |= CAN_READX;
 | 
						|
		if (pwfds)
 | 
						|
			if (FD_ISSET(m_sock, pwfds))
 | 
						|
				itmp |= CAN_WRITEX;
 | 
						|
		iret = itmp;
 | 
						|
	}
 | 
						|
 | 
						|
	if (pwfds)
 | 
						|
		delete pwfds;
 | 
						|
	if (prfds)
 | 
						|
		delete prfds;
 | 
						|
 | 
						|
	return iret;
 | 
						|
}
 |