최종완료보고 버전
This commit is contained in:
@@ -0,0 +1,537 @@
|
||||
#ifndef SOCKET__H_
|
||||
#define SOCKET__H_
|
||||
|
||||
#ifdef MASS_SERVICE_SERVER
|
||||
#define FD_SETSIZE 2048
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#pragma once
|
||||
|
||||
//#pragma comment(lib, "wsock32.lib") // old ver
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
|
||||
#if _MSC_VER <= 1200
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
#include <ws2tcpip.h> // getaddrinfo
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h> // sockaddr_in
|
||||
#include <arpa/inet.h> // inet_ntoa()
|
||||
#include <netdb.h> // gethostbyname()
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef int SOCKET;
|
||||
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
|
||||
#define closesocket close
|
||||
|
||||
#define SD_BOTH SHUT_RDWR
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
extern inline int SockErrorNo()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return WSAGetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern inline int GetAddrByHostName(const char * pAddress, struct sockaddr_in * pSai) // blocking operation
|
||||
{
|
||||
struct hostent * pHe;
|
||||
|
||||
// resolve host address
|
||||
if ((pHe = gethostbyname(pAddress)) == NULL)
|
||||
{
|
||||
#if defined(_WIN32) && _MSC_VER <= 1200
|
||||
return WSAGetLastError();
|
||||
#else
|
||||
struct addrinfo aiHints;
|
||||
struct addrinfo *aiList = NULL;
|
||||
struct addrinfo *aiPtr = NULL;
|
||||
int retVal;
|
||||
|
||||
memset(&aiHints, 0, sizeof(aiHints));
|
||||
aiHints.ai_family = AF_INET;
|
||||
aiHints.ai_socktype = SOCK_STREAM;
|
||||
aiHints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
if ((retVal = getaddrinfo(pAddress, NULL, &aiHints, &aiList)))
|
||||
return SockErrorNo();
|
||||
|
||||
for(aiPtr = aiList; aiPtr != NULL; aiPtr = aiPtr->ai_next)
|
||||
{
|
||||
if (aiPtr->ai_family == AF_INET)
|
||||
{
|
||||
memset(pSai, 0, sizeof(struct sockaddr_in));
|
||||
memcpy(pSai, aiPtr->ai_addr, sizeof(struct sockaddr_in));
|
||||
freeaddrinfo(aiList);
|
||||
return 0; // success
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(aiList);
|
||||
return SOCKET_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
memset(pSai, 0, sizeof(struct sockaddr_in));
|
||||
pSai->sin_addr.s_addr = *(u_long *)pHe->h_addr_list[0];
|
||||
pSai->sin_family = AF_INET;
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
extern inline void SetSockAddr(struct sockaddr_in * pSai, const char * pIp, u_short nPort)
|
||||
{
|
||||
memset(pSai, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
pSai->sin_addr.s_addr = inet_addr(pIp);
|
||||
pSai->sin_family = AF_INET;
|
||||
pSai->sin_port = htons(nPort);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class HSocket : public HObject
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ERR_TIMEOUT = WSAETIMEDOUT
|
||||
#else
|
||||
ERR_TIMEOUT = ETIMEDOUT
|
||||
#endif
|
||||
};
|
||||
|
||||
public:
|
||||
HSocket()
|
||||
{
|
||||
m_fdSocket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
virtual ~HSocket()
|
||||
{
|
||||
if (m_fdSocket != INVALID_SOCKET)
|
||||
closesocket(m_fdSocket);
|
||||
}
|
||||
|
||||
inline SOCKET GetSocket();
|
||||
inline void SetSocket(SOCKET sock);
|
||||
|
||||
inline SOCKET Create(int nDomain, int nType, int nProtocol = 0);
|
||||
inline int Close();
|
||||
|
||||
inline int Bind(u_short nPort);
|
||||
inline int Bind(struct sockaddr_in * psaiLocal);
|
||||
inline int Bind(const char * pAddress, u_short nPort);
|
||||
|
||||
inline int Listen(int nBackLog);
|
||||
inline SOCKET Accept(HSocket & sockClient, char * pszPeerIp = NULL, u_short * pnPeerPort = NULL);
|
||||
|
||||
inline int Connect(struct sockaddr_in * psaiRemote);
|
||||
inline int Connect(const char * pHostAddress, u_short nPort);
|
||||
|
||||
inline int Send(const char * pData, int nLen, int nFlags = 0);
|
||||
inline int Receive(char * pBuf, int nLen, int nFlags = 0);
|
||||
inline int SendTo(const char * pData, int nLen, int flags, struct sockaddr_in * pSaiRemote);
|
||||
inline int ReceiveFrom(char * pBuf, int nLen, int nFlags = 0, struct sockaddr_in * pSaiRemote = NULL, socklen_t * pnSaiLen = NULL);
|
||||
|
||||
inline int GetLocalAddress(struct sockaddr_in * psai);
|
||||
inline int GetLocalAddress(char * pBuf, u_short * pnPort);
|
||||
|
||||
inline int GetPeerAddress(struct sockaddr_in * psai);
|
||||
inline int GetPeerAddress(char * pBuf, u_short * pnPort);
|
||||
|
||||
inline int SetSockOpt(int nLevel, int nOptname, const char * pOptval,
|
||||
int nOptlen);
|
||||
inline int GetSockOpt(int nLevel, int nOptname, char * pOptval,
|
||||
int * pnOptlen);
|
||||
|
||||
inline int GetSockOptError();
|
||||
|
||||
inline int SetNonBlockMode(bool bNonBlock);
|
||||
|
||||
//
|
||||
inline bool TimoutConnect(struct sockaddr_in * psaiRemote, unsigned long nTimeout, bool bRestoreSyncMode, int * pnError);
|
||||
inline bool TimoutConnect(const char * pHostAddress, u_short nPort, unsigned long nTimeout, bool bRestoreSyncMode, int * pnError);
|
||||
inline bool WaitForSending(unsigned long nTimeout, int * pnError); // for non-block mode, *pnError = errno or WSAGetLastError()
|
||||
inline bool WaitForReceiving(unsigned long nTimeout, int * pnError); // for non-block mode, *pnError = errno or WSAGetLastError()
|
||||
|
||||
protected:
|
||||
SOCKET m_fdSocket;
|
||||
};
|
||||
|
||||
inline SOCKET HSocket::GetSocket()
|
||||
{
|
||||
return m_fdSocket;
|
||||
}
|
||||
|
||||
inline void HSocket::SetSocket(SOCKET sock)
|
||||
{
|
||||
m_fdSocket = sock;
|
||||
}
|
||||
|
||||
inline SOCKET HSocket::Create(int nDomain, int nType, int nProtocol)
|
||||
{
|
||||
return (m_fdSocket = socket(nDomain, nType, nProtocol));
|
||||
}
|
||||
|
||||
inline int HSocket::Close()
|
||||
{
|
||||
int nResult = closesocket(m_fdSocket);
|
||||
m_fdSocket = INVALID_SOCKET;
|
||||
return nResult;
|
||||
}
|
||||
|
||||
inline int HSocket::Bind(u_short nPort)
|
||||
{
|
||||
return Bind(NULL, nPort);
|
||||
}
|
||||
|
||||
inline int HSocket::Bind(struct sockaddr_in * psaiLocal)
|
||||
{
|
||||
return bind(m_fdSocket, (struct sockaddr *)psaiLocal, sizeof(struct sockaddr));
|
||||
}
|
||||
|
||||
inline int HSocket::Bind(const char * pAddress, u_short nPort)
|
||||
{
|
||||
struct sockaddr_in sai;
|
||||
memset(&sai, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
if (pAddress == NULL || pAddress[0] == '\0')
|
||||
sai.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
else
|
||||
sai.sin_addr.s_addr = inet_addr(pAddress);
|
||||
|
||||
sai.sin_family = AF_INET;
|
||||
sai.sin_port = htons(nPort);
|
||||
|
||||
return bind(m_fdSocket, (struct sockaddr *)&sai, sizeof(struct sockaddr));
|
||||
}
|
||||
|
||||
inline int HSocket::Listen(int nBackLog)
|
||||
{
|
||||
return listen(m_fdSocket, nBackLog);
|
||||
}
|
||||
|
||||
inline SOCKET HSocket::Accept(HSocket & sockClient, char * pszPeerIp, u_short * pnPeerPort)
|
||||
{
|
||||
if (pszPeerIp != NULL || pnPeerPort != NULL)
|
||||
{
|
||||
struct sockaddr_in sai;
|
||||
socklen_t len = sizeof(struct sockaddr);
|
||||
|
||||
SOCKET sock = (sockClient.m_fdSocket = accept(m_fdSocket, (struct sockaddr *)&sai, &len));
|
||||
|
||||
if (pszPeerIp != NULL)
|
||||
strcpy(pszPeerIp, inet_ntoa(sai.sin_addr));
|
||||
if (pnPeerPort != NULL)
|
||||
*pnPeerPort = ntohs(sai.sin_port);
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
return (sockClient.m_fdSocket = accept(m_fdSocket, NULL, NULL));
|
||||
}
|
||||
|
||||
inline int HSocket::Connect(struct sockaddr_in * psaiRemote)
|
||||
{
|
||||
return connect(m_fdSocket, (struct sockaddr *)psaiRemote, sizeof(struct sockaddr));
|
||||
}
|
||||
|
||||
inline int HSocket::Connect(const char * pHostAddress, u_short nPort)
|
||||
{
|
||||
struct sockaddr_in sai;
|
||||
memset(&sai, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
sai.sin_addr.s_addr = inet_addr(pHostAddress);
|
||||
sai.sin_family = AF_INET;
|
||||
sai.sin_port = htons(nPort);
|
||||
|
||||
return connect(m_fdSocket, (struct sockaddr *)&sai, sizeof(struct sockaddr));
|
||||
}
|
||||
|
||||
inline int HSocket::Send(const char * pData, int nLen, int nFlags)
|
||||
{
|
||||
return send(m_fdSocket, pData, nLen, nFlags);
|
||||
}
|
||||
|
||||
inline int HSocket::Receive(char * pBuf, int nLen, int nFlags)
|
||||
{
|
||||
return recv(m_fdSocket, pBuf, nLen, nFlags);
|
||||
}
|
||||
|
||||
inline int HSocket::SendTo(const char * pData, int nLen, int flags, struct sockaddr_in * pSaiRemote)
|
||||
{
|
||||
return sendto(m_fdSocket, pData, nLen, flags, (struct sockaddr *)pSaiRemote, sizeof(struct sockaddr));
|
||||
}
|
||||
|
||||
inline int HSocket::ReceiveFrom(char * pBuf, int nLen, int nFlags, struct sockaddr_in * pSaiRemote, socklen_t * pnSaiLen)
|
||||
{
|
||||
return recvfrom(m_fdSocket, pBuf, nLen, nFlags, (struct sockaddr *)pSaiRemote, pnSaiLen);
|
||||
}
|
||||
|
||||
inline int HSocket::GetLocalAddress(struct sockaddr_in * psai)
|
||||
{
|
||||
socklen_t len = sizeof(struct sockaddr);
|
||||
return getsockname(m_fdSocket, (struct sockaddr *)psai, &len);
|
||||
}
|
||||
|
||||
inline int HSocket::GetLocalAddress(char * pBuf, u_short * pnPort)
|
||||
{
|
||||
struct sockaddr_in sai;
|
||||
socklen_t len = sizeof(struct sockaddr);
|
||||
|
||||
if (getsockname(m_fdSocket, (struct sockaddr *)&sai, &len) < 0)
|
||||
return SockErrorNo();
|
||||
|
||||
if (pBuf)
|
||||
strcpy(pBuf, inet_ntoa(sai.sin_addr));
|
||||
|
||||
if (pnPort)
|
||||
*pnPort = ntohs(sai.sin_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int HSocket::GetPeerAddress(struct sockaddr_in * psai)
|
||||
{
|
||||
socklen_t len = sizeof(struct sockaddr);
|
||||
|
||||
return getpeername(m_fdSocket, (struct sockaddr *)psai, &len);
|
||||
}
|
||||
|
||||
inline int HSocket::GetPeerAddress(char * pBuf, u_short * pnPort)
|
||||
{
|
||||
struct sockaddr_in sai;
|
||||
socklen_t len = sizeof(struct sockaddr);
|
||||
|
||||
if (getpeername(m_fdSocket, (struct sockaddr *)&sai, &len) < 0)
|
||||
return SockErrorNo();
|
||||
|
||||
if (pBuf)
|
||||
strcpy(pBuf, inet_ntoa(sai.sin_addr));
|
||||
|
||||
if (pnPort)
|
||||
*pnPort = ntohs(sai.sin_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int HSocket::SetSockOpt(int nLevel, int nOptname, const char * pOptval, int nOptlen)
|
||||
{
|
||||
return setsockopt(m_fdSocket, nLevel, nOptname, pOptval, nOptlen);
|
||||
}
|
||||
|
||||
inline int HSocket::GetSockOpt(int nLevel, int nOptname, char * pOptval, int * pnOptlen)
|
||||
{
|
||||
return getsockopt(m_fdSocket, nLevel, nOptname, pOptval, (socklen_t *)pnOptlen);
|
||||
}
|
||||
|
||||
inline int HSocket::GetSockOptError()
|
||||
{
|
||||
int nOptVal;
|
||||
int nOptLen = sizeof(int);
|
||||
if (getsockopt(m_fdSocket, SOL_SOCKET, SO_ERROR, (char *)(&nOptVal), (socklen_t *)&nOptLen) < 0)
|
||||
return SockErrorNo();
|
||||
|
||||
return nOptVal;
|
||||
}
|
||||
|
||||
inline int HSocket::SetNonBlockMode(bool bNonBlock)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ULONG nFlags = bNonBlock;
|
||||
return ioctlsocket(m_fdSocket, FIONBIO, &nFlags);
|
||||
#else
|
||||
int nFlags = fcntl(m_fdSocket, F_GETFL, 0);
|
||||
return fcntl(m_fdSocket, F_SETFL, (bNonBlock ? nFlags | O_NONBLOCK : nFlags & ~O_NONBLOCK));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool HSocket::TimoutConnect(struct sockaddr_in * psaiRemote,
|
||||
unsigned long nTimeout, bool bRestoreSyncMode, int * pnError)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ULONG nFlags = 1;
|
||||
if (ioctlsocket(m_fdSocket, FIONBIO, &nFlags) < 0)
|
||||
#else
|
||||
int nFlags = fcntl(m_fdSocket, F_GETFL, 0);
|
||||
if (fcntl(m_fdSocket, F_SETFL, nFlags | O_NONBLOCK) < 0)
|
||||
#endif
|
||||
{
|
||||
*pnError = SockErrorNo();
|
||||
return false;
|
||||
}
|
||||
|
||||
socklen_t len = sizeof(struct sockaddr);
|
||||
int nResult;
|
||||
if ((nResult = connect(m_fdSocket, (struct sockaddr *)psaiRemote, len)) < 0)
|
||||
{
|
||||
*pnError = SockErrorNo();
|
||||
#ifdef _WIN32
|
||||
if (*pnError != WSAEINPROGRESS && *pnError != WSAEWOULDBLOCK)
|
||||
#else
|
||||
if (*pnError != EINPROGRESS)
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
fd_set fsRead, fsWrite;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&fsRead);
|
||||
FD_SET(m_fdSocket, &fsRead);
|
||||
fsWrite = fsRead;
|
||||
|
||||
tv.tv_sec = nTimeout / 1000;
|
||||
tv.tv_usec = (nTimeout % 1000) * 1000;
|
||||
|
||||
if ((nResult = select((int)(m_fdSocket + 1), &fsRead, &fsWrite, NULL, &tv)) == 0)
|
||||
{
|
||||
*pnError = ERR_TIMEOUT;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FD_ISSET(m_fdSocket, &fsRead) || FD_ISSET(m_fdSocket, &fsWrite))
|
||||
{
|
||||
len = sizeof(nResult);
|
||||
if (getsockopt(m_fdSocket, SOL_SOCKET, SO_ERROR, (char *)&nResult, &len) < 0)
|
||||
{
|
||||
*pnError = SOCKET_ERROR;
|
||||
return false; // Solaris pending error
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*pnError = SOCKET_ERROR; // select error: m_fdSocket not set
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bRestoreSyncMode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
nFlags = 0;
|
||||
if (ioctlsocket(m_fdSocket, FIONBIO, &nFlags) < 0)
|
||||
#else
|
||||
if (fcntl(m_fdSocket, F_SETFL, nFlags) < 0)
|
||||
#endif
|
||||
{
|
||||
*pnError = SockErrorNo();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*pnError = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool HSocket::TimoutConnect(const char * pHostAddress, u_short nPort, unsigned long nTimeout, bool bRestoreSyncMode, int * pnError)
|
||||
{
|
||||
struct sockaddr_in sai;
|
||||
memset(&sai, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
sai.sin_addr.s_addr = inet_addr(pHostAddress);
|
||||
sai.sin_family = AF_INET;
|
||||
sai.sin_port = htons(nPort);
|
||||
|
||||
return TimoutConnect(&sai, nTimeout, bRestoreSyncMode, pnError);
|
||||
}
|
||||
|
||||
inline bool HSocket::WaitForSending(unsigned long nTimeout, int * pnError)
|
||||
{
|
||||
fd_set fsWrite;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&fsWrite);
|
||||
FD_SET(m_fdSocket, &fsWrite);
|
||||
|
||||
tv.tv_sec = nTimeout / 1000;
|
||||
tv.tv_usec = (nTimeout % 1000) * 1000;
|
||||
|
||||
int nResult = select((int)m_fdSocket + 1, NULL, &fsWrite, NULL, nTimeout ? &tv : NULL);
|
||||
if (nResult < 0)
|
||||
{
|
||||
*pnError = SockErrorNo();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nResult == 0 || FD_ISSET(m_fdSocket, &fsWrite) == 0)
|
||||
{
|
||||
*pnError = ERR_TIMEOUT;
|
||||
return false;
|
||||
}
|
||||
|
||||
*pnError = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool HSocket::WaitForReceiving(unsigned long nTimeout, int * pnError)
|
||||
{
|
||||
fd_set fsRead;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&fsRead);
|
||||
FD_SET(m_fdSocket, &fsRead);
|
||||
|
||||
tv.tv_sec = nTimeout / 1000;
|
||||
tv.tv_usec = (nTimeout % 1000) * 1000;
|
||||
|
||||
int nResult = select((int)m_fdSocket + 1, &fsRead, NULL, NULL, nTimeout ? &tv : NULL);
|
||||
if (nResult < 0)
|
||||
{
|
||||
*pnError = SockErrorNo();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nResult == 0 || FD_ISSET(m_fdSocket, &fsRead) == 0)
|
||||
{
|
||||
*pnError = ERR_TIMEOUT;
|
||||
return false;
|
||||
}
|
||||
|
||||
*pnError = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern inline int TcpCompleteSend(SOCKET sock, const char * pszPacket, int nPacketSize)
|
||||
{
|
||||
int nSentSize;
|
||||
const char * pszPacketOffset = pszPacket;
|
||||
while (nPacketSize > 0)
|
||||
{
|
||||
nSentSize = send(sock, pszPacketOffset, nPacketSize, 0);
|
||||
if (nSentSize <= 0)
|
||||
{
|
||||
//HLOG(HLOG_ERROR, "[ERROR], EmailSender, Failed to send.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nPacketSize -= nSentSize;
|
||||
pszPacketOffset += nSentSize;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // SOCKET__H_
|
||||
Reference in New Issue
Block a user