📄 sgipcomm.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 + -