📄 socket.cpp
字号:
{
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 + -