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

📄 socket.cpp

📁 经常用到的 socketAPI
💻 CPP
📖 第 1 页 / 共 2 页
字号:
{
	struct timeval	sTimeout;
	sTimeout.tv_sec = nSec;
	sTimeout.tv_usec = nMs;
	fd_set iRset;
	FD_ZERO(&iRset);
	FD_SET(m_iSocket,&iRset);
	
	int fd =select(m_iSocket+1,&iRset,NULL,NULL,&sTimeout);
	if(fd == 0)
		return TIMEROUT_;
    if(fd<0)
		    #if defined(WIN32)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
            #else
			throw CSocketException(strerror(errno), __FILE__, __LINE__);
            #endif

	if( Accept(connectsock) ) return 0;
	else return -1;		
}

/////////////////////////////////////////////////////////////////////////
// 函数名:Open
// 作  用:服务器端使用,LISTEN
// 参  数:
// 返回值:void
// 修  改:
/////////////////////////////////////////////////////////////////////////
void CTcpSocket::Open(int iBackLog/*=5*/)
{
	SockREUSEADDR();
	Listen(iBackLog);
}



/////////////////////////////////////////////////////////////////////////
// 函数名:Open
// 作  用:客户端使用 connect  连接成功保存本地ip,系统分配端口号
// 参  数:CInetAddress
// 返回值:bool 是否连接成功 
// 修  改:
/////////////////////////////////////////////////////////////////////////
bool CTcpSocket::Open(const CInetAddress& stInetAddr)
{
	if (connect(m_iSocket, (struct sockaddr*)&(stInetAddr.m_stInetAddr), sizeof(stInetAddr.m_stInetAddr)) < 0)
	{
        #if defined(WIN32)
		if ( (m_bBlock && errno == EINTR) || (!m_bBlock)) 
        #else
		if ( (m_bBlock && errno == EINTR) || (!m_bBlock && errno == EINPROGRESS) )
        #endif
		{
			m_eState = S_CONNECTING;
			return false;
		}
            #if defined(WIN32)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
            #else
			throw CSocketException(strerror(errno), __FILE__, __LINE__);
            #endif
	}

	m_eState = S_CONNECTED;	

	//存储本地ip,端口号
	StoreLocalIP_PORT();

	return true;
}

/////////////////////////////////////////////////////////////////////////
// 函数名:Open
// 作  用:客户端使用 connect  连接成功保存本地ip,系统分配端口号
// 参  数:ip地址,端口号
// 返回值:bool 是否连接成功 
// 修  改:
/////////////////////////////////////////////////////////////////////////
bool CTcpSocket::Open(const char *IpAddr,tcport_t port)
{
	CInetAddress tmpInetAddr(IpAddr,port);//对方地址,端口号
    return Open(tmpInetAddr);
}


int  CTcpSocket::OpenwithTmOut(const char *IpAddr,tcport_t port,int nSec,int nMs/*=0*/)
{
    CInetAddress tmpInetAddr(IpAddr,port);//对方地址,端口号
	return OpenwithTmOut(tmpInetAddr,nSec,nMs);
}

/////////////////////////////////////////////////////////////////////////
// 函数名:OpenwithTmOut
// 作  用:客户端使用 connect  连接成功保存本地ip,系统分配端口号
// 参  数:CInetAddress,延时秒数,毫秒数
// 返回值:NOMORL_成功, DOWN_,UNKNOWNERR_,TIMEROUT_
// 修  改:
/////////////////////////////////////////////////////////////////////////
int  CTcpSocket::OpenwithTmOut(const CInetAddress& stInetAddr,int nSec,int nMs/*=0*/)
{
    SetBlock(false);
    int Ret = ::connect(m_iSocket, (struct sockaddr*)&(stInetAddr.m_stInetAddr), sizeof(stInetAddr.m_stInetAddr));
	#if !defined (WIN32) 
	if(Ret && errno!= EINPROGRESS)
	{	
		SetBlock(true);
		m_eState = S_CONNECTING;
		return DOWN_;
	} 
	#endif
    if(Ret==0)
	{
		m_eState = S_CONNECTED;	
		//存储本地ip,端口号
		StoreLocalIP_PORT();
		//SetBlock(true);	
		return NOMORL_;
	}			
	SetBlock(true);	
	fd_set rdevents;
	fd_set wrevents;
	fd_set exevents;
	FD_ZERO( &rdevents );
	FD_SET( m_iSocket, &rdevents );
	wrevents = rdevents;
	exevents = rdevents;
	struct timeval tv;
	tv.tv_sec = nSec;
	tv.tv_usec = nMs;
	int rc = select( m_iSocket + 1, &rdevents, &wrevents, &exevents, &tv );
	if ( rc < 0 )
		return UNKNOWNERR_;
	else if ( rc == 0 )
		return TIMEROUT_;
	else if(Isconnected(&rdevents, &wrevents, &exevents)) 
	{
		m_eState = S_CONNECTED;	
		//存储本地ip,端口号
		StoreLocalIP_PORT();	
		return NOMORL_;
	}
	else
		return DOWN_;
}




bool CTcpSocket::CheckOpen(long lSec, long lUSec)
{
	fd_set rset, wset;
	FD_ZERO(&rset);
	FD_SET(m_iSocket, &rset);
	FD_ZERO(&wset);
	FD_SET(m_iSocket, &wset);

	while (true)
	{
		struct timeval stTimeVal;
		stTimeVal.tv_sec = lSec;
		stTimeVal.tv_usec = lUSec;	
		
		int i = 0;	
		i = select(m_iSocket + 1, &rset, &wset, NULL, (lSec == 0 && lUSec == 0) ? NULL : &stTimeVal);
		if (i == 0)	//timeout
			return false;
		
		if (i < 0)
		{
			if (errno == EINTR)
			{
				if (OnCheckOpenIntr())
					continue;
				else
					return false;
			}

			return false;
		}
		
		if (FD_ISSET(m_iSocket, &rset) || FD_ISSET(m_iSocket, &wset))
		{  

#if defined(WIN32)
               int optval ;
				int Len=sizeof(optval);
			if (getsockopt(m_iSocket, SOL_SOCKET, SO_ERROR, (char*)&optval ,/*(int*)*/&Len) < 0	//solaris < 0 when error occurs
					|| errno < 0)
			    throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);

#else
			socklen_t tLen = sizeof(errno);
			if (getsockopt(m_iSocket, SOL_SOCKET, SO_ERROR, &errno,/*(int*)*/&tLen) < 0	//solaris < 0 when error occurs
					|| errno < 0)
			    throw CSocketException(strerror(errno), __FILE__, __LINE__);
#endif

			m_eState = S_CONNECTED;
			return true;
		}
		
		throw CSocketException("unknown error occurs", __FILE__, __LINE__);
	}
}




void CTcpSocket::Listen(int iBackLog)
{
	if (listen(m_iSocket, iBackLog) < 0)
		
#if defined(WIN32)
		throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
#else
	    throw CSocketException(strerror(errno), __FILE__, __LINE__);
#endif
}

/////////////////////////////////////////////////////////////////////////
// 函数名:ReadLine
// 作  用:读取一行直到'\n'为止,阻塞调用
// 参  数:接受缓冲,缓冲长度len
// 返回值:>0接收实际长度,=0 EOF,<0出错
// 修  改:
/////////////////////////////////////////////////////////////////////////
int CTcpSocket::ReadLine(char *bufptr,size_t len)
{
	
	char* bufx=bufptr;
	char* bp;
	int cnt=0;
	char b[1024];
	char c;
	while (--len >0)
	{
		if(--cnt<=0)
		{
			cnt=recv(m_iSocket,b,sizeof(b),0);
			if(cnt<0)
			{
				if(errno==EINTR)
				{
					len++;  //the  while  will  decrement
					continue;
				} 
				return -1;
			}
			if(cnt==0)
				return 0;   //EOF
			bp=b;
		}
		c=*bp++;
		*bufptr++=c;
		if(c=='\n')
		{
			*bufptr='\0';
			return bufptr-bufx;
		}
	}
	return -1;
}

/////////////////////////////////////////////////////////////////////////
// 函数名:Writen
// 作  用:写指定的长度到sock,直到完成给定长度
// 参  数:写缓冲,缓冲长度nSize
// 返回值:实际写长度
// 修  改:
/////////////////////////////////////////////////////////////////////////
int CTcpSocket::Writen(const char* pch, const int nSize, const int nSecs,const int nMs)
{
	int nBytesSent = 0;
	int nBytesThisTime;
	const char* pch1 = pch;
	do 
	{
		nBytesThisTime = Send(pch1, nSize, nSecs,nMs);
		nBytesSent += nBytesThisTime;
		pch1 += nBytesThisTime;
	} while(nBytesSent < nSize);
	
	return nBytesSent;
}

//timeout return TIMEROUT_
//EOF     return
int CTcpSocket::Readn( char* pch, const int nSize, const int nSecs,const int nMs)
{
	fd_set rset;
	FD_ZERO(&rset);
	FD_SET(m_iSocket, &rset);
	timeval tv = {nSecs, nMs};
	int selret;

	int nBytesLeft = nSize;
	int nBytesThisTime=0;
	char *pch1 = pch;
    while(nBytesLeft>0)
	{
		if(selret=select(m_iSocket+1, &rset, NULL, NULL, &tv) == 0) 
		{
			return TIMEROUT_;//超时
		}

		if(selret<0)
		{
			#if defined(WIN32)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
			#else
            throw CSocketException(strerror(errno), __FILE__, __LINE__);
			#endif				
		}
		nBytesThisTime=recv(m_iSocket,pch1, nBytesLeft,0);//fin return EOF
		if(nBytesThisTime<0) //read err?
		{
			if(errno==EINTR)//interrupted by signal?
				continue;
            #if defined(WIN32)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
		    #else
			throw CSocketException(strerror(errno), __FILE__, __LINE__);
            #endif	     
		}
		if(nBytesThisTime==0) //EOF?
			return nSize-nBytesLeft;
		pch1 += nBytesThisTime;
		nBytesLeft -= nBytesThisTime;
	}
	return nSize-nBytesLeft;
}

/////////////////////////////////////////////////////////////////////////
// 函数名:Send
// 作  用:写到sock
// 参  数:带超时功能的写缓冲,缓冲长度nSize
// 返回值:实际写长度
// 修  改:
/////////////////////////////////////////////////////////////////////////
int CTcpSocket::Send(const char* pch, const int nSize, const int nSecs,const int nMs)
{
	
	fd_set  wset;
	FD_ZERO(&wset);
	FD_SET(m_iSocket, &wset);
             int selret;
	timeval tv = {nSecs, nMs};
	if(selret=select(m_iSocket+1, NULL, &wset, NULL, &tv) == 0)
            return TIMEROUT_;//超时       
	
	if(selret<0)
	{
            #if defined(WIN32)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
	#else
			throw CSocketException(strerror(errno), __FILE__, __LINE__);
            #endif	 
	}
    return BaseSend(pch, nSize);
}

/////////////////////////////////////////////////////////////////////////
// 函数名:Receive
// 作  用:读sock
// 参  数:带超时功能的读,缓冲长度nSize
// 返回值:实际读长度
// 修  改:
/////////////////////////////////////////////////////////////////////////
int CTcpSocket::Receive(char* pch, const int nSize, const int nSecs,const int nMs)
{
	fd_set rset;
	FD_ZERO(&rset);
	FD_SET(m_iSocket, &rset);
	int selret;
	timeval tv = {nSecs, nMs};
	if(selret=select(m_iSocket+1, &rset, NULL, NULL, &tv) == 0) 
	{
           return TIMEROUT_;//超时
	}
	if(selret<0)
	{
            #if defined(WIN32)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
		    #else
			throw CSocketException(strerror(errno), __FILE__, __LINE__);
            #endif	 
	}

    return BaseRead(pch, nSize);
}


int CTcpSocket::BaseSend(const char* pch, const int nSize)
{

	int nBytesSent;
	                     
	if((nBytesSent = send(m_iSocket, pch, nSize,0)) < 0) 
	//if((nBytesSent = ::write(m_iSocket, pch, nSize)) < 0) 
	{
		cerr<<"the m_iSock is "<<m_iSocket<<'\n';
            #if defined(WIN32)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
		    #else
			throw CSocketException(strerror(errno), __FILE__, __LINE__);
            #endif	 
	}
	return nBytesSent;
}

int CTcpSocket::BaseRead(char* pch, const int nSize)
{
	int nBytesReceived=recv(m_iSocket,(char*) pch, nSize,0);
	if(nBytesReceived < 0) //err?
	{
            #if defined(WIN32)
			throw CSocketException(STRERROR_WIN(WIN32_SYS_WINSOCK), __FILE__, __LINE__);
		    #else
			throw CSocketException(strerror(errno), __FILE__, __LINE__);
            #endif	 
	}
//	else if(nBytesReceived==0)//EOF ?
	return nBytesReceived;
}

#if defined(WIN32)
bool CTcpSocket::Isconnected(fd_set *rd, fd_set *wr, fd_set *ex )
{
	WSASetLastError( 0 );
	if ( !FD_ISSET( m_iSocket, rd ) && !FD_ISSET( m_iSocket, wr ) )
		return false;
	if ( FD_ISSET( m_iSocket, ex ) )
		return false;
	return TRUE;
}
#else
bool CTcpSocket::Isconnected(fd_set *rd, fd_set *wr, fd_set *ex )
{
	int err;
	#if defined(WIN32)
	int len = sizeof( err );
	#else
	socklen_t len = sizeof( err );
	#endif

	errno = 0;			/* assume no error */
	if ( !FD_ISSET( m_iSocket, rd ) && !FD_ISSET( m_iSocket, wr ) )
		return false;
	if ( getsockopt( m_iSocket, SOL_SOCKET, SO_ERROR, &err, &len ) < 0 )
		return false;
	errno = err;		/* in case we're not connected */
	return err == 0;
}

#endif

}

⌨️ 快捷键说明

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