Files
mir_server/sdk/system/CustomSocketLinux.cpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

418 lines
7.6 KiB
C++

#include <cstring>
#include <errno.h>
#include "SocketConfig.h"
#ifdef CONFIG_USE_LINUX_SOCKET
using namespace wylib::inet::socket;
INT CCustomSocket::setBlockMode(const bool block)
{
u_long ulock;
if ( block == m_boBlock )
return 0;
if ( m_nSocket != INVALID_SOCKET )
{
ulock = block ? 0 : 1;
if ( ioctl( m_nSocket, FIONBIO, &ulock ) )
{
return errno;
}
}
m_boBlock = block;
return 0;
}
VOID CCustomSocket::close()
{
if ( m_nSocket != INVALID_SOCKET )
{
if ( m_boConnected )
{
Disconnected();
}
shutdown(m_nSocket, SHUT_RDWR);
::close(m_nSocket);
m_nSocket = INVALID_SOCKET;
}
m_boConnected = false;
m_boConnecting = false;
m_boBlock = true;
}
INT CCustomSocket::shutDown(const INT sd)
{
int nErr = 0;
if ( m_boConnected && m_nSocket != INVALID_SOCKET )
{
nErr = shutdown( m_nSocket, sd );
if ( nErr == 0 )
{
m_boConnected = false;
m_boConnecting = false;
Disconnected();
}
}
return 0;
}
INT CCustomSocket::bind(const ULONG addr, const INT port)
{
INT nErr;
SOCKADDR_IN addrin;
memset(&addrin, 0, sizeof(addrin));
addrin.sin_family = AF_INET;
//addrin.sin_addr.s_addr = addr;
addrin.sin_addr.s_addr = htonl(INADDR_ANY);
addrin.sin_port = htons((u_short)port);
int tmp =1;
setsockopt(m_nSocket,SOL_SOCKET,SO_REUSEADDR,&tmp, sizeof(tmp));
nErr = ::bind( m_nSocket, (const sockaddr*)&addrin, sizeof(addrin) );
//if ( nErr == 0 )
{
m_LocalAddr = addrin;
}
//return nErr;
return 0;
}
INT CCustomSocket::bind(const char * addr, const INT port)
{
INT nErr;
SOCKADDR_IN addrin;
memset(&addrin, 0, sizeof(addrin));
addrin.sin_family = AF_INET;
addrin.sin_addr.s_addr = inet_addr(addr);
addrin.sin_port = htons((u_short)port);
int tmp=1;
setsockopt(m_nSocket,SOL_SOCKET,SO_REUSEADDR,&tmp, sizeof(tmp));
nErr = ::bind( m_nSocket, (const sockaddr*)&addrin, sizeof(addrin) );
if ( nErr == 0 )
{
m_LocalAddr = addrin;
}
return nErr;
/*
struct hostent *phost;
#ifdef UNICODE
wylib::string::CWideString ws(addr);
wylib::string::CAnsiString *as = ws.toAStr();
phost = gethostbyname(*as);
delete as;
#else
phost = gethostbyname(addr);
#endif
if ( phost )
{
in_addr addr;
addr.s_addr = *(u_long*)phost->h_addr_list[0];
return bind( addr.s_addr, port );
}
return errno;
*/
}
INT CCustomSocket::getRecvBufSize(ULONG *size)
{
unsigned int oplen = sizeof(*size);
return getsockopt( m_nSocket, SOL_SOCKET, SO_RCVBUF, (char*)size, &oplen );
}
INT CCustomSocket::setRecvBufSize(ULONG size)
{
return setsockopt(m_nSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&size, sizeof(size));
}
INT CCustomSocket::getSendBufSize(ULONG *size)
{
unsigned int oplen = sizeof(*size);
return getsockopt( m_nSocket, SOL_SOCKET, SO_SNDBUF, (char*)size, &oplen );
}
INT CCustomSocket::setSendBufSize(ULONG size)
{
return setsockopt( m_nSocket, SOL_SOCKET, SO_SNDBUF, (const char*)&size, sizeof(size) );
}
INT CCustomSocket::listen(const INT backlog)
{
return ::listen( m_nSocket, backlog );
}
int CCustomSocket::connect(const char * addr, const INT port)
{
struct hostent *phost = NULL;
#ifdef UNICODE
wylib::string::CWideString ws(addr);
wylib::string::CAnsiString *as = ws.toAStr();
phost = gethostbyname(*as);
delete as;
#else
phost = gethostbyname(addr);
#endif
if ( phost )
{
in_addr addr_;
addr_.s_addr = inet_addr(addr);//*(u_long*)(phost->h_addr_list[0]);
return connect( addr_.s_addr, port );
}
return -1;
}
int CCustomSocket::accept(SOCKET *socket, unsigned long wait_msec, PSOCKADDR_IN addr)
{
int nErr;
fd_set set;
timeval tv;
unsigned int addrsize;
FD_ZERO( &set );
FD_SET( m_nSocket, &set );
tv.tv_sec = long(wait_msec / 1000);
tv.tv_usec = long( (wait_msec %1000)* 1000);
nErr = select( int(m_nSocket + 1), &set, NULL, NULL, &tv );
if ( nErr < 0 )
return nErr;
if ( nErr > 0 )
{
addrsize = sizeof(*addr);
*socket = ::accept( m_nSocket, (sockaddr*)addr, &addrsize );
if ( *socket == INVALID_SOCKET )
{
return nErr;
}
return 0;
}
return SOCKET_ERROR - 1;
}
INT CCustomSocket::connect(const ULONG addr, const INT port)
{
int nErr;
SOCKADDR_IN addrin;
memset(&addrin, 0, sizeof(addrin));
addrin.sin_family = AF_INET;
addrin.sin_addr.s_addr = addr;
addrin.sin_port = htons(port);
nErr = ::connect( m_nSocket, (sockaddr*)&addrin, sizeof(addrin) );
if ( nErr == 0 )
{
m_boConnected = true;
m_boConnecting = false;
Connected();
}
else
{
nErr = errno;
if ( nErr == ENOBUFS)
{
nErr = 0;
m_boConnected = false;
m_boConnecting = true;
}
}
return nErr;
}
INT CCustomSocket::connect(const char * addr, const INT port, int timeout)
{
struct hostent *phost;
#ifdef UNICODE
wylib::string::CWideString ws(addr);
wylib::string::CAnsiString *as = ws.toAStr();
phost = gethostbyname(*as);
delete as;
#else
phost = gethostbyname(addr);
#endif
if ( phost )
{
in_addr addr;
addr.s_addr = *(u_long*)phost->h_addr_list[0];
return connect( addr.s_addr, port, timeout);
}
return -1;
}
INT CCustomSocket::connect(const ULONG addr, const INT port, int timeout)
{
int nErr;
SOCKADDR_IN addrin;
memset(&addrin, 0, sizeof(addrin));
addrin.sin_family = AF_INET;
addrin.sin_addr.s_addr = addr;
addrin.sin_port = htons(port);
// 超时需要在非阻塞下
unsigned long mode = 1;
ioctl(m_nSocket, FIONBIO, &mode);
nErr = 0;
if ( ::connect( m_nSocket, (sockaddr*)&addrin, sizeof(addrin) ) == 0 )
{
m_boConnected = true;
m_boConnecting = false;
Connected();
}
else
{
// 设置回阻塞
mode = 0;
ioctl(m_nSocket, FIONBIO, &mode);
// 使用select超时connet
struct timeval tm={timeout,0};
fd_set wset;
FD_ZERO(&wset);
FD_SET(m_nSocket, &wset);
if( ::select(m_nSocket+1, NULL, &wset, NULL, &tm) > 0)
{
int error=-1, len=sizeof(int);
getsockopt(m_nSocket, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
if(error == 0)
{
m_boConnected = true;
m_boConnecting = false;
Connected();
return 0;
}
}
// 执行到这里说明连接不成功
nErr = errno;
if ( nErr == ENOBUFS)
{
nErr = 0;
m_boConnected = false;
m_boConnecting = true;
}
}
return nErr;
}
int CCustomSocket::createSocket(SOCKET *socket, const INT af, const int type, const int protocol)
{
*socket = ::socket( af, type, protocol );
if ( *socket == INVALID_SOCKET )
{
return *socket;
}
m_nSocket = *socket ;
return 0;
}
/* 原来的recv的实现
int nErr = ::recv( m_nSocket, (char*)buf, len, flags );
if ( nErr == 0 )
{
close();
}
else if ( nErr < 0 )
{
if ( !m_boBlock )
{
nErr = errno;
if ( nErr != ENOBUFS )
{
SocketError( nErr );
nErr = -1;
}
else
{
nErr = SOCKET_ERROR - 1;
}
}
}
return nErr;
*/
int CCustomSocket::recv(LPVOID buf, INT size, const INT flags)
{
if ( !buf || size < 1) return 0;
int r = 0 ;
r = ::recv(m_nSocket, buf, size, flags);
if( r == 0 )
{
// 关闭连接
close();
return 0 ;
}
else if( r < 0 )
{
return -1 ;
}
return r;
}
INT CCustomSocket::send(LPVOID buf, INT len, const INT flags)
{
int nRet, nErr;
char *ptr = (char*)buf;
nRet = 0;
while ( len > 0 )
{
nErr = ::send( m_nSocket, (char*)ptr, len, flags );
if ( nErr == 0 )
{
nRet = 0;
close();
break;
}
else if ( nErr < 0 )
{
if ( !m_boBlock )
{
if ( errno == EINTR ) // 因为发生中断,中断处理后可以继续发送,所以此处应选择暂时退出函数, 然后再继续调用send进行接收数据
{
continue ;
}
else if(errno == EAGAIN)
{
Sleep(10);
continue ;
}
}
nRet = nErr;
break;
}
else
{
nRet += nErr;
ptr += nErr;
len -= nErr;
}
}
return nRet;
}
#endif