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

📄 sgipcomm.cpp

📁 联通的短信网关平台。 sp 使用。 如果想自己用vc 开发短信业务
💻 CPP
字号:
/*****************************
 ** FILE: SGIPComm.cpp   ****
 ** Auth: Liaomch         ****
 ** Date: 2003-06-19      ****
 ** Modify:               ****
 *****************************/
 
#include <netdb.h>
#include "SGIPComm.h"
#include "sgip.h"
#include "SGIPPkg.h"

extern unsigned int g_nSeqNo; //系列号
extern char g_cSrcID[11];//节点编号
extern char g_cClientIP[16];
extern int  g_iLocalPort;
extern char g_cServerIP[16];
extern int	 g_iSrvPort;
extern int	 g_iAcceptNum;
extern char g_cRUserName[16];
extern char g_cRUserPwd[16];
extern char g_cLUserName[16];
extern char g_cLUserPwd[16];
extern char g_cSpNum[21];
extern char g_cCorpID[7];
 
CSGIPComm::CSGIPComm()
{
	m_pkg = new CSGIPPkg();
	pthread_mutex_init(&m_Connect_mutex , NULL);
	pthread_mutex_init(&m_send_mutex , NULL);
	pthread_mutex_init(&m_recv_mutex , NULL);
}
 
CSGIPComm::~CSGIPComm()
{
	if (m_pkg != NULL)
		delete m_pkg;
}


int CSGIPComm::DoConnect(const char *pSrv=NULL, int nPort=8801, int nTimes = 3)
{
	pthread_mutex_lock(&m_Connect_mutex);
	int nSockfd = ConnectToSMC(pSrv, nPort, nTimes); 
	pthread_mutex_unlock(&m_Connect_mutex);

	if (nSockfd != END_FAILED)
		printf("DoConnect succeed!\n");
	
	return nSockfd;
}

int CSGIPComm::ConnectToSMC(const char *pSrv=NULL, int nPort=8801, int nTimes = 3)
 {
	int nSockfd = 0;
 	for (int i=0; i<nTimes; i++)
 	{
		if (pSrv != NULL)
		{
			if ((nSockfd = TcpConnect((char *)pSrv, nPort)) != END_FAILED)
				break;
		}
		else
		{
			if ((nSockfd = TcpConnect((char *)&g_cServerIP, g_iSrvPort)) != END_FAILED)
				break;		
		}
	}

	if (nSockfd == END_FAILED)
	{
		printf("TcpConnect error!\n");
		return nSockfd;
	}
	else
		printf("TcpConnect succeed!\n");

	
	//send login msg and recv the response;

	char cBuf[1024];
	memset(&cBuf, 0, sizeof(cBuf));

	SGIP_BIND_BODY stBind;
	int nBufLen = 0;
	m_pkg->DeComposePackage(SGIP_BIND, (SGIP_MSG_BODY &)stBind, (char *)cBuf, &nBufLen);
	if (nBufLen == 0)
		return END_FAILED;
	
	if ( SendToSMC(nSockfd, (const char *)&cBuf, m_pkg->GetMessageLen(SGIP_BIND)) )
	{
		memset(&cBuf, 0, sizeof(cBuf));
		int nRcvMsgLen = sizeof(cBuf);
		int nRet = -1;
		nRet = RecvFromSMC(nSockfd, (char *)&cBuf, &nRcvMsgLen, 60);
		if ((nRet == END_SUCCEED) && (nRcvMsgLen >= 4))
		{
			int nStatus = m_pkg->GetPackageResult((const char *)&cBuf);
			if ((nStatus == END_SUCCEED)&&(nRcvMsgLen > 4))
			{
				return nSockfd;
			}
			else
			{
				close(nSockfd);
				nSockfd = -1;
				return END_FAILED;
			}
		}
		else
			printf("recv error!\n");
	}
	else
		printf("Send bind mesg error!\n");

	//error!
	close(nSockfd);
	nSockfd = -1;
	return END_FAILED;
 } 
 
int CSGIPComm::DisConnect(int nSockfd)
 {
	if (nSockfd < 0)
		return END_FAILED;

	char cBuf[1024];
	memset(&cBuf, 0, sizeof(cBuf));

	m_pkg->NewPackage(SGIP_UNBIND, (char *)cBuf);

	if ( SendToSMC(nSockfd, (const char *)&cBuf, sizeof(SGIP_UNBIND_MSG)) )
	{
		memset(&cBuf, 0, sizeof(cBuf));
		int nRcvMsgLen = sizeof(cBuf);
		int nRet = -1;
		nRet = RecvFromSMC(nSockfd, (char *)&cBuf, &nRcvMsgLen, 30);
		if ((nRet == END_SUCCEED) && (nRcvMsgLen >= 4))
		{
			int nMsgType = m_pkg->GetPackageType((const char *)&cBuf);
			if ((nMsgType == (int)SGIP_UNBIND_RESP)&&(nRcvMsgLen > 4))
			{
				close(nSockfd);
				nSockfd = -1;
				return END_SUCCEED;
			}
		}
	}
	//error!
	close(nSockfd);
	nSockfd = -1;
	return END_FAILED;
 } 

bool CSGIPComm::SendToSMC(int nSockfd, const char *pBuf, int nLen)
 {
 	if (nSockfd <= 0)
 		return false;
 		
 	int nSendLen = 0;
	const char *p = pBuf;
	int nLeftLen = nLen;

	//pthread_mutex_lock(&m_send_mutex);
 	for (; nLeftLen > 0; nLeftLen -= nSendLen)
 	{
 		p += nSendLen;
 		nSendLen = write(nSockfd, (void *)p, nLeftLen);
 		if (nSendLen < 0)
 		{
 			if (errno == EINTR)
 				nSendLen = 0;
 			else
			{
				//pthread_mutex_unlock(&m_send_mutex);
 				return false;
			}
 		} 		
 	} 
	//pthread_mutex_unlock(&m_send_mutex);
	if (nLeftLen == 0)
 		return true;
	else 
		return false;
 }
 
int CSGIPComm::RecvFromSMC(int nSockfd, char *pBuf, int *pLen, int nTimeout)
{
	int        i_read = 0 ;
	int        i_len = 0;
	int			nBufLen = *pLen;

	*pLen = 0;

	if(nSockfd < 0)
	{    
		return END_FAILED ;
	}
	//pthread_mutex_lock(&m_recv_mutex);
    /*
    ** read file length 
    */
	i_read = tcp_recv(nSockfd, pBuf, 4, nTimeout);

    if ( i_read == -1 )
    {
		//pthread_mutex_unlock(&m_recv_mutex);
        return(END_FAILED);
    }

	//added by liaomch 2003-10-17
	//超时收到长度为0
    if ( i_read == 0)
    {
		//pthread_mutex_unlock(&m_recv_mutex);
        return (-2);//TIMEOUT
    }
	//end added by liaomch
	
    //turn_byte_order((unsigned char *)&i_len,(unsigned char *)pBuf,(short int)4);

	int nTemp = 0;
	memcpy(&nTemp, pBuf, sizeof(int));
	i_len = ntohl(nTemp);  

	if (i_len > nBufLen)
		return( END_FAILED );
		//return -3;//要收的太长了

    i_read = tcp_recv(nSockfd, pBuf+4, i_len-4, nTimeout);
	//pthread_mutex_unlock(&m_recv_mutex);

    if ( i_read == -1 )
    {
        return( END_FAILED );
    }

	//added by liaomch 2003-10-17
	//超时收到长度为0
    if ( i_read == 0)
    {
		//pthread_mutex_unlock(&m_recv_mutex);
        return (-2);//TIMEOUT
    }
	//end added by liaomch

    if ( i_read + 4 != i_len )
    {
		printf("===received a bad package!===\n"
			"\tmust recv = %d, real recv = %d\n", i_len, (i_read));
        return(END_FAILED);
    }

	*pLen = i_len;
    return (END_SUCCEED);
}

int CSGIPComm::tcp_recv(int nSockfd, char *pBuf, int nLen, int nTimeOut)
{
	char   *ps_buf = pBuf;
	int    l_read_so_far = 0;
	int    l_read = 0;
	int    l_len = 0;

	if (nSockfd < 0)
		return END_FAILED;

	//time_t tStartRead = time(NULL);

	//time out set
	fd_set	rset;
	struct timeval	tval;
	
	memset(&tval, 0, sizeof(tval));
	
	if( nTimeOut < 0 )
		nTimeOut=0;
	
	FD_ZERO(&rset);
	FD_SET(nSockfd,&rset);
	
	tval.tv_sec = nTimeOut;
	tval.tv_usec = 0 ;
	//-------------
	
	while ( l_read_so_far < nLen ) 
	{
		ps_buf += l_read_so_far;
		l_len = nLen - l_read_so_far;
		
		if((select(nSockfd+1,&rset,NULL,NULL,nTimeOut?&tval:NULL)) == 0 )
		{
			printf("recv time out return!\n");
			return	0;//time out
		}

		l_read = read(nSockfd, ps_buf, l_len);

		//read returns by itself (not because of timed out)
		if ( l_read <= 0 ) 
		{
			perror("read error!");

			if (errno == EINTR)
			{
 				l_read = 0;
				return END_FAILED;
			}
 			else
 				return END_FAILED;
		} 
		else  if ( l_read > 0 ) 
		{
			l_read_so_far += l_read;
		}
    }

    return( l_read_so_far );
} 

 
 int CSGIPComm::ConnectTimeOut(int sockfd, const struct sockaddr *saptr, socklen_t socklen, int secs)
{
	int	flags;
	int	n,error;
	socklen_t	len;
	fd_set	rset,wset;
	struct timeval	tval;

	if(sockfd <= 0 || saptr == (struct sockaddr *)0)
		return	END_FAILED;
	if( secs < 0 )
		secs=0;
	error=0;
	flags=fcntl(sockfd,F_GETFL,0);
	fcntl(sockfd,F_SETFL,flags|O_NONBLOCK);

	if((n=connect(sockfd,saptr,socklen)) < 0 )
    {
	    if(errno != EINPROGRESS)
        { 
			return(END_FAILED);
        }
    }
	if(n == 0 )
		goto	done;
	FD_ZERO(&rset);
	FD_SET(sockfd,&rset);

	wset =rset;
	tval.tv_sec = secs;
	tval.tv_usec = 0 ;

	if(( n=select(sockfd+1,&rset,&wset,NULL,secs?&tval:NULL)) == 0 )
	{
		close(sockfd);
		errno=ETIMEDOUT;
		return	END_FAILED;
	}
	
	if(FD_ISSET(sockfd,&rset) || FD_ISSET(sockfd,&wset)) 
	{
		len=sizeof(error);
		if( getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len) < 0 )
			return	END_FAILED;
	}
	else
		return	END_FAILED;
done:
	fcntl(sockfd,F_SETFL,flags);
	if(error)
	{
		close(sockfd);
		errno=error;
		return	END_FAILED;
	}
	return	END_SUCCEED;
}

//********************************************************************
//	TcpConnect
//		Build up a TCP connection to host at port.  This is used at
//		client part, returns the socket fd on success, or -1 on error
//********************************************************************
int CSGIPComm::TcpConnect(char* host, int port)
{
	int fd;
	struct sockaddr_in sin;

	if((fd=socket(AF_INET, SOCK_STREAM, 0))<0)
	{
		return END_FAILED;
	}	

	// resolv host to sockaddr_in
	bzero(&sin, sizeof(sin));
	
	//try A.B.C.D numeric IP format address first
	if((sin.sin_addr.s_addr=inet_addr(host))==INADDR_NONE)
	{
		//not numeric IP format, try text format
		struct hostent he;
		//int err, ret;
		//here we use **_r format, 'coz it might be run under multithreading
		//environment.
		//However, some such functions are not standardized yet, so we need
		//know OS platform we are on.
		#ifdef LINUX		
		//LINUX: gethostbyname_r needs six parameters 
		//it return 0 on success, otherwise -1 returned, and 
		//the error code is in err:
		// ERANGE:	buf size too small
		// HOST_NOT_FOUND: Authoritive Answer Host not found
		// TRY_AGAIN:	Non-Authoritive Host not found, or SERVERFAIL
		// NO_RECOVERY: Non recoverable errors, FORMERR, REFUSED, NOTIMP
		// NO_DATA:	    Valid name, no data record of requested type
		// NO_ADDRESS:  no address, look for MX record
		if ((ret=gethostbyname_r(host, &he, buf, sizeof(buf), &p, &err)) < 0 )
		{
			close(fd);
			return END_FAILED; //Resolve failed! :(
		}	
		#elif defined SOLARIS
		//NOTE: be sure to link libnsl.o while compiling
		//     that is, use -lnsl in gcc command options
		//SOLARIS: gethostbyname_r takes five parameters, 
		//it returns the pointer to he in p on success, otherwise NULL
		//the error code is also in err, read above comments
		p=gethostbyname_r(host, &he, buf, sizeof(buf), &err);
		if(!p)
		{
			close(fd);
			return END_FAILED;
		}	
		#endif
		memcpy(&sin.sin_addr.s_addr, he.h_addr, sizeof(sin.sin_addr.s_addr));
	}
	// here we assume we are always under IPv4 environment.
	// If one day shifted to other network environment, such as IPv6,
	// following code should also be under modification
	sin.sin_family=AF_INET;
	sin.sin_port=htons(port);
	//connect
	if(connect(fd, (struct sockaddr*)&sin, sizeof(sin))<0)
	{
		close(fd);
		return END_FAILED;
	}
	return fd;
}	

//********************************************************************
//  TcpConnecto:
//      Time out version.
//      Build up a TCP connection to host at port.  This is used at
//      client part, returns the socket fd on success, or -1 on error
//********************************************************************
int CSGIPComm::TcpConnectTimeOut(char* host, int port,int secs)
{
	int fd;
	struct sockaddr_in sin;

	if((fd=socket(AF_INET, SOCK_STREAM, 0))<0)
	{
		return END_FAILED;
	}	
	// resolv host to sockaddr_in
	bzero(&sin, sizeof(sin));
	
	//try A.B.C.D numeric IP format address first
	if((sin.sin_addr.s_addr=inet_addr(host))==INADDR_NONE)
	{
		//not numeric IP format, try text format
		struct hostent he; 
		//int err, ret;
		//here we use **_r format, 'coz it might be run under multithreading
		//environment.
		//However, some such functions are not standardized yet, so we need
		//know OS platform we are on.
		#ifdef LINUX		
		//LINUX: gethostbyname_r needs six parameters 
		//it return 0 on success, otherwise -1 returned, and 
		//the error code is in err:
		// ERANGE:	buf size too small
		// HOST_NOT_FOUND: Authoritive Answer Host not found
		// TRY_AGAIN:	Non-Authoritive Host not found, or SERVERFAIL
		// NO_RECOVERY: Non recoverable errors, FORMERR, REFUSED, NOTIMP
		// NO_DATA:	    Valid name, no data record of requested type
		// NO_ADDRESS:  no address, look for MX record
		if ((ret=gethostbyname_r(host, &he, buf, sizeof(buf), &p, &err)) < 0 )
		{
			 close(fd);
			 return END_FAILED; //Resolve failed! :(
		}
		#elif defined SOLARIS
		//NOTE: be sure to link libnsl.o while compiling
		//     that is, use -lnsl in gcc command options
		//SOLARIS: gethostbyname_r takes five parameters, 
		//it returns the pointer to he in p on success, otherwise NULL
		//the error code is also in err, read above comments
		p=gethostbyname_r(host, &he, buf, sizeof(buf), &err);
		if(!p)
		{
            close(fd);
			return END_FAILED;
		}	
		#endif
		memcpy(&sin.sin_addr.s_addr, he.h_addr, sizeof(sin.sin_addr.s_addr));
	}
	// here we assume we are always under IPv4 environment.
	// If one day shifted to other network environment, such as IPv6,
	// following code should also be under modification
	sin.sin_family=AF_INET;
	sin.sin_port=htons(port);
	//connect
	if (ConnectTimeOut(fd, (struct sockaddr*)&sin, sizeof(sin),secs)<0 )
	{
		close(fd);
		return END_FAILED;
	}
	return fd;
}

int CSGIPComm::CreateServer(int Iport)
{
	int nSockfd = socket(AF_INET, SOCK_STREAM, 0);
	sockaddr_in  ServerAddr;

	if(nSockfd < 0)
		return END_FAILED;

	memset(&ServerAddr, 0, sizeof(ServerAddr));
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	ServerAddr.sin_port = htons(Iport);
	int nOptVal = 1;

	setsockopt(nSockfd,SOL_SOCKET,SO_REUSEADDR,&nOptVal,sizeof(nOptVal));

	if(bind(nSockfd, (sockaddr*)&ServerAddr, sizeof(ServerAddr)) < 0)
		return END_FAILED;

	if (g_iAcceptNum < 15)
		g_iAcceptNum = 15;
	
	if(listen(nSockfd, g_iAcceptNum) < 0)
		return END_FAILED;

	return nSockfd;
}

int CSGIPComm::GetAccept( int nSockfd )
{
	int  TempSock;
	if(nSockfd < 0)
		return END_FAILED;

	struct sockaddr_in client_addr;
	int nCliAddrLen = 0;
	nCliAddrLen = sizeof(client_addr);
	memset(&client_addr, 0, nCliAddrLen);

	TempSock = accept(nSockfd, (struct sockaddr *)&client_addr, (socklen_t *)&nCliAddrLen);

	if(TempSock < 0)
		return END_FAILED;
	else
	{
		printf("IPADDR:[%s] accepted succeed!\n", inet_ntoa(client_addr.sin_addr));
		return TempSock;
	}
 }

void CSGIPComm::turn_byte_order( unsigned char *ps_dest, unsigned char *ps_src, short t_len )
{
#ifdef SUN_CPU
    memcpy( ps_dest, ps_src, t_len);
#else
    while( t_len > 0 )
    {
        *ps_dest = *(ps_src + t_len -1 );
        ps_dest ++;
        t_len --;
    }
#endif
	return;
}

⌨️ 快捷键说明

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