From 2c880cccb3668a2b42d7c07ef148931320f31c89 Mon Sep 17 00:00:00 2001 From: kiritow <1362050620@qq.com> Date: Thu, 27 Jul 2017 19:52:58 +0800 Subject: [PATCH] Initial Commit --- .gitignore | 6 ++ Readme.md | 5 + gsock.cpp | 299 +++++++++++++++++++++++++++++++++++++++++++++++++++++ gsock.h | 68 ++++++++++++ 4 files changed, 378 insertions(+) create mode 100644 .gitignore create mode 100644 Readme.md create mode 100644 gsock.cpp create mode 100644 gsock.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c0156c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bin/ +obj/ +*.cbp +*.depend +*.layout + diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..442323d --- /dev/null +++ b/Readme.md @@ -0,0 +1,5 @@ +# General Socket Wrapper + +GSOCK is a project created by [Kiritow](https://github.com/kiritow). + +Licensed under MIT diff --git a/gsock.cpp b/gsock.cpp new file mode 100644 index 0000000..c709f91 --- /dev/null +++ b/gsock.cpp @@ -0,0 +1,299 @@ +/** General Socket Wrapper +* Created By Kiritow. (https://github.com/kiritow) +* Licensed under MIT +*/ + +/** Version: 2.1 */ + +#include "gsock.h" + + +#ifdef __WIN32__ +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define closesocket close +using BYTE = unsigned char; +#endif + +#include +#include + +class _init_winsock2_2_class +{ +public: + _init_winsock2_2_class() + { + /// Windows Platform need WinSock2.DLL initialization. +#ifdef __WIN32__ + WORD wd; + WSAData wdt; + wd=MAKEWORD(2,2); + int ret=WSAStartup(wd,&wdt); + if(ret<0) + { + throw std::runtime_error("Unable to load winsock2.dll. "); + } +#endif + } + ~_init_winsock2_2_class() + { + /// Windows Platform need WinSock2.DLL clean up. +#ifdef __WIN32__ + WSACleanup(); +#endif + } +} _init_winsock2_2_obj; + + +class sock::_impl +{ +public: + int sfd; + sockaddr_in saddr; +}; + +sock::sock() : _pp(new _impl) +{ + _pp->sfd=socket(AF_INET,SOCK_STREAM,0); +} + +//private +sock::sock(int SocketValue) : _pp(new _impl) +{ + _pp->sfd=SocketValue; +} + +sock::sock(sock&& tmp) +{ + _pp=std::move(tmp._pp); +} + +sock& sock::operator = (sock&& tmp) +{ + if(_pp) + { + closesocket(_pp->sfd); + } + _pp=std::move(tmp._pp); + return *this; +} + +sock::~sock() +{ + if(_pp) + { + closesocket(_pp->sfd); + } +} + +int sock::connect(const std::string& IPStr,int Port) +{ + // refs + int& sfd=_pp->sfd; + sockaddr_in& saddr=_pp->saddr; + + memset(&saddr,0,sizeof(saddr)); + saddr.sin_addr.s_addr=inet_addr(IPStr.c_str()); + saddr.sin_port=htons(Port); + saddr.sin_family=AF_INET; + return ::connect(sfd,(sockaddr*)&saddr,sizeof(saddr)); +} + +int sock::send(const char* Buffer,int Length) +{ + return ::send(_pp->sfd,Buffer,Length,0); +} + +int sock::recv(char* Buffer,int MaxToRecv) +{ + return ::recv(_pp->sfd,Buffer,MaxToRecv,0); +} + +int sock::getsendtime(int& _out_Second, int& _out_uSecond) +{ + // refs + int& sfd=_pp->sfd; + + struct timeval outtime; + int _not_used_t; + int ret=getsockopt(sfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&outtime,&_not_used_t); + if(ret<0) return ret; + /// We don't know why, but on Windows, 1 Second means 1000. +#ifdef __WIN32__ + _out_Second=outtime.tv_sec/1000; + _out_uSecond=outtime.tv_usec; +#else + _out_Second=outtime.tv_sec; + _out_uSecond=outtime.tv_usec; +#endif + + return ret; +} + +int sock::getrecvtime(int& _out_Second, int& _out_uSecond) +{ + // refs + int& sfd=_pp->sfd; + + struct timeval outtime; + int _not_used_t; + int ret=getsockopt(sfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&outtime,&_not_used_t); + if(ret<0) return ret; + /// We don't know why, but on Windows, 1 Second means 1000. +#ifdef __WIN32__ + _out_Second=outtime.tv_sec/1000; + _out_uSecond=outtime.tv_usec; +#else + _out_Second=outtime.tv_sec; + _out_uSecond=outtime.tv_usec; +#endif + + return ret; +} + +int sock::setsendtime(int Second) +{ + // refs + int& sfd=_pp->sfd; + + struct timeval outtime; + /// We don't know why, but on Windows, 1 Second means 1000. +#ifdef __WIN32__ + outtime.tv_sec=Second*1000; + outtime.tv_usec=0; +#else + outtime.tv_sec=Second; + outtime.tv_usec=0; +#endif + + return setsockopt(sfd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&outtime,sizeof(outtime)); +} + +int sock::setrecvtime(int Second) +{ + // refs + int& sfd=_pp->sfd; + + struct timeval outtime; + /// We don't know why, but on Windows, 1 Second means 1000. +#ifdef __WIN32__ + outtime.tv_sec=Second*1000; + outtime.tv_usec=0; +#else + outtime.tv_sec=Second; + outtime.tv_usec=0; +#endif + + return setsockopt(sfd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&outtime,sizeof(outtime)); +} + + + + +class serversock::_impl +{ +public: + int sfd; + sockaddr_in saddr; +}; + +serversock::serversock() : _pp(new _impl) +{ + _pp->sfd=socket(AF_INET,SOCK_STREAM,0); +} + +serversock::~serversock() +{ + closesocket(_pp->sfd); +} + +int serversock::bind(int Port) +{ + // refs + int& sfd=_pp->sfd; + sockaddr_in& saddr=_pp->saddr; + + memset(&saddr,0,sizeof(saddr)); + saddr.sin_addr.s_addr=INADDR_ANY; + saddr.sin_port=htons(Port); + saddr.sin_family=AF_INET; + return ::bind(sfd,(sockaddr*)&saddr,sizeof(saddr)); +} + +int serversock::set_reuse() +{ + // refs + int& sfd=_pp->sfd; + + int opt=1; + return setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&opt,sizeof(opt)); +} + +int serversock::listen(int MaxCount) +{ + // refs + int& sfd=_pp->sfd; + + return ::listen(sfd,MaxCount); +} + +sock&& serversock::accept() +{ + sock s; + int tmp=sizeof(s._pp->saddr); + int ret=::accept(_pp->sfd,(sockaddr*)&(s._pp->saddr),&tmp); + if(ret<0) + { + s._pp->sfd=-1;/// Bad Socket + } + else + { + s._pp->sfd=ret; + } + return std::move(s); +} + + + +int DNSResolve(const std::string& HostName, std::string& _out_IPStr) +{ + /// Use getaddrinfo instead + struct addrinfo hints; + memset(&hints,0,sizeof(hints)); + hints.ai_family=AF_UNSPEC; + hints.ai_socktype=SOCK_STREAM; + hints.ai_protocol=IPPROTO_TCP; + + struct addrinfo* result=nullptr; + + int ret=getaddrinfo(HostName.c_str(),NULL,&hints,&result); + if(ret!=0) + { + return -1;/// API Call Failed. + } + for(struct addrinfo* ptr=result; ptr!=nullptr; ptr=ptr->ai_next) + { + switch(ptr->ai_family) + { + case AF_INET: + sockaddr_in* addr=(struct sockaddr_in*) (ptr->ai_addr) ; + _out_IPStr=inet_ntoa(addr->sin_addr); + return 0; + break; + } + } + /// Unknown error. + return -2; +} + diff --git a/gsock.h b/gsock.h new file mode 100644 index 0000000..cfc76fb --- /dev/null +++ b/gsock.h @@ -0,0 +1,68 @@ +/** General Socket Wrapper +* Created By Kiritow. (https://github.com/kiritow) +* Licensed under MIT +*/ + +/** Version: 2.1 */ + +#pragma once + +#include +#include + +class sock +{ +public: + sock(); + sock(const sock&)=delete; + sock& operator = (const sock&)=delete; + sock(sock&&); + sock& operator = (sock&&); + ~sock(); + + int connect(const std::string& IPStr,int Port); + + template + int send(const T&); + + template + int recv(T&); + + int send(const char* Buffer,int Length); + int recv(char* Buffer,int MaxToRecv); + + int getsendtime(int& _out_Second,int& _out_uSecond); + int getrecvtime(int& _out_Second,int& _out_uSecond); + + int setsendtime(int Second); + int setrecvtime(int Second); + +private: + sock(int); + friend class serversock; + + class _impl; + std::unique_ptr<_impl> _pp; +}; + +class serversock +{ +public: + serversock(); + serversock(const serversock&)=delete; + serversock& operator = (const serversock&) =delete; + serversock(serversock&&)=delete; + serversock& operator = (serversock&&) =delete; + ~serversock(); + + int bind(int Port); + int set_reuse(); + int listen(int MaxCount); + + sock&& accept(); +private: + class _impl; + std::unique_ptr<_impl> _pp; +}; + +int DNSResolve(const std::string& HostName,std::string& _out_IPStr);