Update GSock

This commit is contained in:
Kirigaya Kazuto 2018-05-05 15:37:50 +08:00
parent eb2337ae22
commit 6aebdca0bc
2 changed files with 156 additions and 213 deletions

282
gsock.cpp
View File

@ -71,121 +71,90 @@ public:
} }
} _init_winsock2_2_obj; } _init_winsock2_2_obj;
struct vsock::_impl
struct sock::_impl
{ {
int sfd; int sfd;
sockaddr_in saddr; bool created;
bool created;
}; };
sock::sock() : _pp(new _impl) vsock::vsock() : _vp(new _impl)
{ {
myliblog("sock::sock() %p", this); _vp->created=false;
_pp->created=false;
} }
//private vsock::vsock(vsock&& v)
sock::sock(int SocketValue) : _pp(new _impl)
{ {
myliblog("sock::sock(int) %p\n",this); _vp=v._vp;
v._vp=nullptr;
_pp->created=true;
_pp->sfd=SocketValue;
} }
sock::sock(sock&& tmp) vsock& vsock::operator = (vsock&& v)
{ {
myliblog("sock::sock(sock&&) %p <- %p \n",this,&tmp); this->~vsock();
_vp=v._vp;
_pp=tmp._pp; v._vp=nullptr;
tmp._pp=nullptr; return *this;
} }
sock& sock::operator = (sock&& tmp) vsock::~vsock()
{ {
myliblog("sock::operator = (sock&&) %p <= %p\n",this,&tmp); if(_vp)
{
if(_vp->created)
{
myliblog("Socket closed: [%d] in %p\n",_vp->sfd,this);
closesocket(_vp->sfd);
if(_pp) _vp->created=false;
{ }
if(_pp->created)
{
myliblog("Socket closed: [%d] in %p\n",_pp->sfd,this);
closesocket(_pp->sfd);
}
delete _pp; delete _vp;
} _vp=nullptr;
}
_pp=tmp._pp;
tmp._pp=nullptr;
return *this;
}
sock::~sock()
{
myliblog("sock::~sock() %p\n",this);
if(_pp)
{
if(_pp->created)
{
myliblog("Socket closed: [%d] in %p\n",_pp->sfd,this);
closesocket(_pp->sfd);
}
delete _pp;
}
} }
int sock::connect(const std::string& IPStr,int Port) int sock::connect(const std::string& IPStr,int Port)
{ {
myliblog("sock::connect() %p\n",this); myliblog("sock::connect() %p\n",this);
if(_pp->created) if(_vp->created)
{ {
return -2; return -2;
} }
_pp->sfd=socket(AF_INET,SOCK_STREAM,0); _vp->sfd=socket(AF_INET,SOCK_STREAM,0);
if(_pp->sfd<0) if(_vp->sfd<0)
{ {
myliblog("socket() returns %d. WSAGetLastError: %d\n",_pp->sfd,WSAGetLastError()); myliblog("socket() returns %d. WSAGetLastError: %d\n",_vp->sfd,WSAGetLastError());
return -3; return -3;
} }
myliblog("Socket created: [%d] in %p\n",_pp->sfd,this); myliblog("Socket created: [%d] in %p\n",_pp->sfd,this);
_pp->created=true; _vp->created=true;
// refs struct sockaddr_in saddr;
int& sfd=_pp->sfd;
sockaddr_in& saddr=_pp->saddr;
memset(&saddr,0,sizeof(saddr)); memset(&saddr,0,sizeof(saddr));
saddr.sin_addr.s_addr=inet_addr(IPStr.c_str()); saddr.sin_addr.s_addr=inet_addr(IPStr.c_str());
saddr.sin_port=htons(Port); saddr.sin_port=htons(Port);
saddr.sin_family=AF_INET; saddr.sin_family=AF_INET;
return ::connect(sfd,(sockaddr*)&saddr,sizeof(saddr)); return ::connect(_vp->sfd,(sockaddr*)&saddr,sizeof(saddr));
} }
int sock::send(const void* Buffer,int Length) int sock::send(const void* Buffer,int Length)
{ {
return ::send(_pp->sfd,(const char*)Buffer,Length,0); return ::send(_vp->sfd,(const char*)Buffer,Length,0);
} }
int sock::recv(void* Buffer,int MaxToRecv) int sock::recv(void* Buffer,int MaxToRecv)
{ {
return ::recv(_pp->sfd,(char*)Buffer,MaxToRecv,0); return ::recv(_vp->sfd,(char*)Buffer,MaxToRecv,0);
} }
int sock::getsendtime(int& _out_Second, int& _out_uSecond) int sock::getsendtime(int& _out_Second, int& _out_uSecond)
{ {
// refs
int& sfd=_pp->sfd;
struct timeval outtime; struct timeval outtime;
socklen_t _not_used_t; socklen_t _not_used_t;
int ret=getsockopt(sfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&outtime,&_not_used_t); int ret=getsockopt(_vp->sfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&outtime,&_not_used_t);
if(ret<0) return ret; if(ret<0) return ret;
/// We don't know why, but on Windows, 1 Second means 1000. /// We don't know why, but on Windows, 1 Second means 1000.
#ifdef _WIN32 #ifdef _WIN32
@ -201,12 +170,9 @@ int sock::getsendtime(int& _out_Second, int& _out_uSecond)
int sock::getrecvtime(int& _out_Second, int& _out_uSecond) int sock::getrecvtime(int& _out_Second, int& _out_uSecond)
{ {
// refs
int& sfd=_pp->sfd;
struct timeval outtime; struct timeval outtime;
socklen_t _not_used_t; socklen_t _not_used_t;
int ret=getsockopt(sfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&outtime,&_not_used_t); int ret=getsockopt(_vp->sfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&outtime,&_not_used_t);
if(ret<0) return ret; if(ret<0) return ret;
/// We don't know why, but on Windows, 1 Second means 1000. /// We don't know why, but on Windows, 1 Second means 1000.
#ifdef _WIN32 #ifdef _WIN32
@ -222,9 +188,6 @@ int sock::getrecvtime(int& _out_Second, int& _out_uSecond)
int sock::setsendtime(int Second) int sock::setsendtime(int Second)
{ {
// refs
int& sfd=_pp->sfd;
struct timeval outtime; struct timeval outtime;
/// We don't know why, but on Windows, 1 Second means 1000. /// We don't know why, but on Windows, 1 Second means 1000.
#ifdef _WIN32 #ifdef _WIN32
@ -235,14 +198,11 @@ int sock::setsendtime(int Second)
outtime.tv_usec=0; outtime.tv_usec=0;
#endif #endif
return setsockopt(sfd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&outtime,sizeof(outtime)); return setsockopt(_vp->sfd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&outtime,sizeof(outtime));
} }
int sock::setrecvtime(int Second) int sock::setrecvtime(int Second)
{ {
// refs
int& sfd=_pp->sfd;
struct timeval outtime; struct timeval outtime;
/// We don't know why, but on Windows, 1 Second means 1000. /// We don't know why, but on Windows, 1 Second means 1000.
#ifdef _WIN32 #ifdef _WIN32
@ -253,7 +213,7 @@ int sock::setrecvtime(int Second)
outtime.tv_usec=0; outtime.tv_usec=0;
#endif #endif
return setsockopt(sfd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&outtime,sizeof(outtime)); return setsockopt(_vp->sfd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&outtime,sizeof(outtime));
} }
//forgive me, but writing code in hospital is really not a good experience. //forgive me, but writing code in hospital is really not a good experience.
@ -273,108 +233,72 @@ static int _sock_getname_call(int sfd,std::string& ip,int& port,_sock_getname_ca
int sock::getlocal(std::string& IPStr,int& Port) int sock::getlocal(std::string& IPStr,int& Port)
{ {
if(!(_pp->created)) if(!(_vp->created))
{ {
return -2; return -2;
} }
return _sock_getname_call(_pp->sfd,IPStr,Port,getsockname); return _sock_getname_call(_vp->sfd,IPStr,Port,getsockname);
} }
int sock::getpeer(std::string& IPStr,int& Port) int sock::getpeer(std::string& IPStr,int& Port)
{ {
if(!(_pp->created)) if(!(_vp->created))
{ {
return -2; return -2;
} }
return _sock_getname_call(_pp->sfd,IPStr,Port,getpeername); return _sock_getname_call(_vp->sfd,IPStr,Port,getpeername);
}
struct serversock::_impl
{
int sfd;
sockaddr_in saddr;
bool created;
};
serversock::serversock() : _pp(new _impl)
{
myliblog("serversock::serversock() %p\n",this);
_pp->created=false;
}
serversock::~serversock()
{
myliblog("serversock::~serversock() %p\n",this);
if(_pp)
{
if(_pp->created)
{
myliblog("Server-Socket closed: [%d] in %p\n",_pp->sfd,this);
closesocket(_pp->sfd);
}
delete _pp;
}
} }
int serversock::bind(int Port) int serversock::bind(int Port)
{ {
myliblog("serversock::bind() %p\n",this); myliblog("serversock::bind() %p\n",this);
if(_pp->created) if(_vp->created)
{ {
return -2; return -2;
} }
_pp->sfd=socket(AF_INET,SOCK_STREAM,0); _vp->sfd=socket(AF_INET,SOCK_STREAM,0);
if(_pp->sfd<0) if(_vp->sfd<0)
{ {
myliblog("socket() returns %d. WSAGetLastError: %d\n",_pp->sfd,WSAGetLastError()); myliblog("socket() returns %d. WSAGetLastError: %d\n",_vp->sfd,WSAGetLastError());
return -3; return -3;
} }
myliblog("Socket created: [%d] in %p\n",_pp->sfd,this); myliblog("Socket created: [%d] in %p\n",_vp->sfd,this);
_pp->created=true; _vp->created=true;
// refs sockaddr_in saddr;
int& sfd=_pp->sfd;
sockaddr_in& saddr=_pp->saddr;
memset(&saddr,0,sizeof(saddr)); memset(&saddr,0,sizeof(saddr));
saddr.sin_addr.s_addr=INADDR_ANY; saddr.sin_addr.s_addr=INADDR_ANY;
saddr.sin_port=htons(Port); saddr.sin_port=htons(Port);
saddr.sin_family=AF_INET; saddr.sin_family=AF_INET;
return ::bind(sfd,(sockaddr*)&saddr,sizeof(saddr)); return ::bind(_vp->sfd,(sockaddr*)&saddr,sizeof(saddr));
} }
int serversock::set_reuse() int serversock::set_reuse()
{ {
// refs socklen_t opt=1;
int& sfd=_pp->sfd; return setsockopt(_vp->sfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&opt,sizeof(opt));
int opt=1;
return setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&opt,sizeof(opt));
} }
int serversock::listen(int MaxCount) int serversock::listen(int MaxCount)
{ {
// refs return ::listen(_vp->sfd,MaxCount);
int& sfd=_pp->sfd;
return ::listen(sfd,MaxCount);
} }
int serversock::accept(sock& _out_s) int serversock::accept(sock& _out_s)
{ {
if(_out_s._pp->created) if(_out_s._vp->created)
{ {
/// _out_s has been connected. /// _out_s has been connected.
return -2; return -2;
} }
sock s; sock s; /// empty socket.
socklen_t tmp=sizeof(s._pp->saddr); sockaddr_in saddr;
int ret=::accept(_pp->sfd,(sockaddr*)&(s._pp->saddr),&tmp); socklen_t saddrsz=sizeof(saddr);
int ret=::accept(_vp->sfd,(sockaddr*)&(saddr),&saddrsz);
if(ret<0) if(ret<0)
{ {
/// accept() call failed. /// accept() call failed.
@ -383,10 +307,10 @@ int serversock::accept(sock& _out_s)
} }
else else
{ {
s._pp->sfd=ret; s._vp->sfd=ret;
s._pp->created=true; s._vp->created=true;
myliblog("Socket opened: [%d] in %p by serversock %p\n",s._pp->sfd,&s,this); myliblog("Socket opened: [%d] in %p by serversock %p\n",s._vp->sfd,&s,this);
/// Move resource. /// Move resource.
_out_s=std::move(s); _out_s=std::move(s);
@ -394,42 +318,38 @@ int serversock::accept(sock& _out_s)
} }
} }
udpsock::udpsock()
struct udpsock::_impl
{ {
int sfd; _vp->sfd = socket(AF_INET, SOCK_DGRAM, 0);
int lastErr; _vp->created = true;
};
udpsock::udpsock() : _pp(new _impl)
{
_pp->sfd = socket(AF_INET, SOCK_DGRAM, 0);
_pp->lastErr = 0;
} }
udpsock::udpsock(udpsock&& x) int udpsock::connect(const std::string& IPStr,int Port)
{ {
_pp = x._pp; sockaddr_in saddr;
x._pp = nullptr; memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(Port);
saddr.sin_addr.s_addr = inet_addr(IPStr.c_str());
return ::connect(_vp->sfd,(const sockaddr*)&saddr,sizeof(saddr));
} }
udpsock& udpsock::operator=(udpsock&& x) int udpsock::broadcast_at(int Port)
{ {
if (_pp) sockaddr_in saddr;
{ memset(&saddr, 0, sizeof(saddr));
// Clean up itself. saddr.sin_family = AF_INET;
this->~udpsock(); saddr.sin_port = htons(Port);
} saddr.sin_addr.s_addr = INADDR_BROADCAST;
_pp = x._pp;
x._pp = nullptr; return ::connect(_vp->sfd,(const sockaddr*)&saddr,sizeof(saddr));
return *this;
} }
udpsock::~udpsock() int udpsock::set_broadcast()
{ {
closesocket(_pp->sfd); socklen_t opt=1;
delete _pp; return ::setsockopt(_vp->sfd,SOL_SOCKET,SO_BROADCAST,(const char*)&opt,sizeof(opt));
} }
int udpsock::bind(int Port) int udpsock::bind(int Port)
@ -439,7 +359,7 @@ int udpsock::bind(int Port)
saddr.sin_family = AF_INET; saddr.sin_family = AF_INET;
saddr.sin_port = htons(Port); saddr.sin_port = htons(Port);
saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_addr.s_addr = INADDR_ANY;
return ::bind(_pp->sfd, (const sockaddr*)&saddr, sizeof(saddr)); return ::bind(_vp->sfd, (const sockaddr*)&saddr, sizeof(saddr));
} }
int udpsock::sendto(const std::string& IPStr, int Port, const void* buffer, int length) int udpsock::sendto(const std::string& IPStr, int Port, const void* buffer, int length)
@ -449,31 +369,43 @@ int udpsock::sendto(const std::string& IPStr, int Port, const void* buffer, int
saddr.sin_family = AF_INET; saddr.sin_family = AF_INET;
saddr.sin_port = htons(Port); saddr.sin_port = htons(Port);
saddr.sin_addr.s_addr = inet_addr(IPStr.c_str()); saddr.sin_addr.s_addr = inet_addr(IPStr.c_str());
return ::sendto(_pp->sfd, (const char*)buffer, length, 0, (const sockaddr*)&saddr, sizeof(saddr)); return ::sendto(_vp->sfd, (const char*)buffer, length, 0, (const sockaddr*)&saddr, sizeof(saddr));
} }
int udpsock::recvfrom(std::string& fromIP, void* buffer, int bufferLength) int udpsock::broadcast(int Port,const void* buffer,int length)
{
sockaddr_in saddr;
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(Port);
saddr.sin_addr.s_addr = INADDR_BROADCAST;
return ::sendto(_vp->sfd, (const char*)buffer, length, 0, (const sockaddr*)&saddr, sizeof(saddr));
}
int udpsock::recvfrom(std::string& fromIP, int& fromPort, void* buffer, int bufferLength)
{ {
sockaddr_in saddr; sockaddr_in saddr;
socklen_t saddrlen = sizeof(saddr); socklen_t saddrlen = sizeof(saddr);
int ret = ::recvfrom(_pp->sfd, (char*)buffer, bufferLength, 0, (sockaddr*)&saddr, &saddrlen); int ret = ::recvfrom(_vp->sfd, (char*)buffer, bufferLength, 0, (sockaddr*)&saddr, &saddrlen);
if (ret < 0) if (ret < 0)
{ {
#ifdef _WIN32 return ret; /// don't bother errno.
_pp->lastErr = WSAGetLastError();
#else
_pp->lastErr = errno;
#endif
} }
fromIP = inet_ntoa(saddr.sin_addr); fromIP = inet_ntoa(saddr.sin_addr);
fromPort = ntohs(saddr.sin_port);
return ret; return ret;
} }
int udpsock::getlasterror() int udpsock::send(const void* buffer,int length)
{ {
return _pp->lastErr; return ::send(_vp->sfd,(const char*)buffer,length,0);
}
int udpsock::recv(void* buffer,int bufferLength)
{
return ::recv(_vp->sfd,(char*)buffer,bufferLength,0);
} }
int DNSResolve(const std::string& HostName, std::string& _out_IPStr) int DNSResolve(const std::string& HostName, std::string& _out_IPStr)

77
gsock.h
View File

@ -9,16 +9,25 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
class sock class vsock
{
protected:
vsock();
vsock(const vsock&)=delete;
vsock& operator = (const vsock&)=delete;
vsock(vsock&&);
vsock& operator = (vsock&&);
~vsock();
vsock(int);
struct _impl;
_impl* _vp;
};
class sock : public vsock
{ {
public: public:
sock();
sock(const sock&)=delete;
sock& operator = (const sock&)=delete;
sock(sock&&);
sock& operator = (sock&&);
~sock();
/// Return: /// Return:
/// 0: Connection Established. No Error. /// 0: Connection Established. No Error.
/// -1: connect() call error. See errno. /// -1: connect() call error. See errno.
@ -50,24 +59,12 @@ public:
int getlocal(std::string& IPStr,int& Port); int getlocal(std::string& IPStr,int& Port);
int getpeer(std::string& IPStr,int& Port); int getpeer(std::string& IPStr,int& Port);
private:
sock(int);
friend class serversock; friend class serversock;
struct _impl;
_impl* _pp;
}; };
class serversock class serversock : public vsock
{ {
public: public:
serversock();
serversock(const serversock&)=delete;
serversock& operator = (const serversock&) =delete;
serversock(serversock&&)=delete;
serversock& operator = (serversock&&) =delete;
~serversock();
/// Return: /// Return:
/// 0: Bind Succeed. No Error. /// 0: Bind Succeed. No Error.
/// -1: bind() call error. See errno. /// -1: bind() call error. See errno.
@ -86,30 +83,44 @@ public:
/// -1: accept() call error. See errno. /// -1: accept() call error. See errno.
/// -2: _out_s is a connected socket, which should not be passed in. /// -2: _out_s is a connected socket, which should not be passed in.
int accept(sock& _out_s); int accept(sock& _out_s);
private:
struct _impl;
_impl* _pp;
}; };
class udpsock class udpsock : public vsock
{ {
public: public:
udpsock(); udpsock();
udpsock(const udpsock&) = delete;
udpsock& operator = (const udpsock&) = delete; /// Use udp socket as tcp socket. (but of course it is not).
udpsock(udpsock&&); /// connect call just copy the target socket data to kernel. See connect() for more info.
udpsock& operator = (udpsock&&); int connect(const std::string& IPStr,int Port);
~udpsock(); int broadcast_at(int Port);
/// Must be called in broadcast mode.
int set_broadcast();
/// Explict bind() call is only need when you have to receive data. /// Explict bind() call is only need when you have to receive data.
int bind(int Port); int bind(int Port);
int sendto(const std::string& IPStr, int Port, const void* buffer, int length); int sendto(const std::string& IPStr, int Port, const void* buffer, int length);
int broadcast(int Port,const void* buffer,int length);
/// Must call bind() before calling recvfrom(). /// Must call bind() before calling recvfrom().
int recvfrom(std::string& fromIP, void* buffer, int bufferLength); int recvfrom(std::string& fromIP, int& fromPort, void* buffer, int bufferLength);
int getlasterror(); /// send() and recv() should only be called after connect(). Or it will fail.
int send(const void* buffer,int length);
int recv(void* buffer,int bufferLength);
};
/// Select
class selector
{
public:
selector();
void clear();
void add_read(const vsock&);
void add_write(const vsock&);
void add_error(const vsock&);
int select(int);
private: private:
struct _impl; struct _impl;
_impl* _pp; _impl* _pp;