From: Myun2 Date: Sat, 19 May 2012 05:27:47 +0000 (+0900) Subject: windows/socket_impl2.hpp Add X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=5d05eb3f524d91d5c2811b8f445be1721392dd40;p=roast%2Froast.git windows/socket_impl2.hpp Add --- diff --git a/roast/include/roast/windows/socket_impl2.hpp b/roast/include/roast/windows/socket_impl2.hpp new file mode 100644 index 00000000..4d6cb0c0 --- /dev/null +++ b/roast/include/roast/windows/socket_impl2.hpp @@ -0,0 +1,321 @@ +// Roast+ License + +/* +*/ +#ifndef __SFJP_ROAST__windows__net__socket_windows_impl_HPP__ +#define __SFJP_ROAST__windows__net__socket_windows_impl_HPP__ + +#include +#include +#include +#include +#pragma comment(lib, "ws2_32.lib") + +////////////////////////////////////////////////// + +namespace roast +{ + class _socket_windows_impl_default_option + { + public: + static unsigned char GetWsockMajorVersion(){ return 2; } + static unsigned char GetWsockMinerVersion(){ return 0; } + }; + + ////////////////////////////////////////////////////////////////////////////////////// + + class _socket_windows_impl_constant + { + public: + typedef ::SOCKET socket_t; + static const socket_t invalid_socket; + }; + const _socket_windows_impl_constant::socket_t _socket_windows_impl_constant::invalid_socket = INVALID_SOCKET; + + //////////////////// + + class _socket_windows_instance_count + { + protected: + static int m_instance_count; + }; + int _socket_windows_instance_count::m_instance_count = 0; + + //////////////////// + + template + class socket_windows_impl_ : public _socket_windows_impl_constant, _socket_windows_instance_count + { + public: + typedef ::u_long in_addr_t; // Linux: in_addr_t + typedef struct ::sockaddr sockaddr_t; + typedef struct ::sockaddr_in sockaddr_in_t; + typedef struct ::addrinfo addrinfo_t; + typedef ::SOCKET socket_t; + //typedef ::fd_set fd_set_t, fdset_t; + + private: + //WSADATA* m_wsaInfo; + ::WSADATA* m_pWsaInfo; + int m_last_error; + ::std::string m_last_error_msg; + //static int m_instance_count; + + void _last_error_zero() + { + m_last_error = 0; + } + void _WSAle_update() + { + m_last_error = ::WSAGetLastError(); + } + + bool _apiret_0true(int apiret) + { + m_last_error = apiret; + return ( apiret == 0 ? true : false ); + } + + bool _apiret_WSAle(int apiret) + { + _WSAle_update(); + return ( apiret == SOCKET_ERROR ? false : true ); + } + + int _myselect(socket_t s, + ::fd_set *readfds, ::fd_set *writefds, ::fd_set *exceptfds, + long timeout_sec, long timeout_usec) + { + struct ::timeval tv; + tv.tv_sec = timeout_sec; + tv.tv_usec = timeout_usec; + + int ret = ::select(0/*Winsock always zero.*/, readfds, writefds, exceptfds, &tv); + _WSAle_update(); + return ret; + } + + public: + socket_windows_impl_() + { + //ZeroMemory(&m_wsaInfo,sizeof(m_wsaInfo)); + m_pWsaInfo = NULL; + m_last_error = 0; + + if ( m_instance_count == 0 ) + init(); + m_instance_count++; + } + virtual ~socket_windows_impl_() + { + m_instance_count--; + if ( m_instance_count == 0 ) + term(); + + if ( m_pWsaInfo != NULL ) + delete m_pWsaInfo; + } + + /////////////////////////////////////////////// + + // init() + bool init() + { + //ZeroMemory(m_wsaInfo,sizeof(m_wsaInfo)); + if ( m_pWsaInfo == NULL ) + m_pWsaInfo = new ::WSADATA(); + ZeroMemory(m_pWsaInfo,sizeof(::WSADATA)); + + WORD wVersionRequested = MAKEWORD( + _OptionT::GetWsockMajorVersion(), + _OptionT::GetWsockMinerVersion()); + + //return _apiret_0true( ::WSAStartup(wVersionRequested, &m_wsaInfo) ); + return _apiret_0true( ::WSAStartup(wVersionRequested, m_pWsaInfo) ); + } + //WSADATA* get_wsadata(){ return &m_wsaInfo; } + ::WSADATA* get_wsadata(){ return m_pWsaInfo; } + + // term() + bool term() + { + return _apiret_0true( ::WSACleanup() ); + } + + /////////////////////////////////////////// + + // socket() + socket_t socket(int af, int type, int protocol) + { + socket_t s = ::socket(af, type, protocol); + _WSAle_update(); + return s; + } + + bool getaddrinfo(const char *node, const char *service, + const addrinfo_t *hints, addrinfo_t **res) + { + return _apiret_0true( ::getaddrinfo(node, service, hints, res) ); + } + + void freeaddrinfo(addrinfo_t *ai) + { + ::freeaddrinfo(ai); + } + + int getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, int flags) + { + return _apiret_0true( ::getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) ); + } + + // connect() + bool connect(socket_t s, const sockaddr_t *addr, int addrlen) + { + return _apiret_WSAle( ::connect(s, addr, addrlen) ); + } + + // bind + bool bind(socket_t s, const sockaddr_t *addr, int len ) + { + return _apiret_WSAle( ::bind(s, addr, len) ); + } + + // listen + bool listen(socket_t s, int max_queueing) + { + return _apiret_WSAle( ::listen(s, max_queueing) ); + } + + // accept + socket_t accept(socket_t s, sockaddr_t *addr_out, int *len_out ) + { + socket_t accepted_socket = ::accept(s, addr_out, len_out); + _WSAle_update(); + return accepted_socket; + } + + // shutdown() + // ‚±‚̊֐”‚Ń\ƒPƒbƒg‚Ì‘—M‚©ŽóM‚ð‚Å‚«‚È‚­‚µ‚Ü‚·B + // closesocket ŠÖ”‚Ń\ƒPƒbƒg‚ð•Â‚¶‚é‘O‚ɁA‚±‚̊֐”‚Őڑ±‚ð’âŽ~iƒVƒƒƒbƒgƒ_ƒEƒ“j‚µ‚Ä‚­‚¾‚³‚¢B + /* + WSAAsyncSelect ŠÖ”‚ðŽg‚Á‚Ä FD_CLOSE ’Ê’m‚ð“o˜^‚µ‚Ä‚­‚¾‚³‚¢B + shutdown ‚Ì how ‚É SD_SEND ‚ð“n‚µ‚Ä‚­‚¾‚³‚¢B + + “Á‚ɁAWindows Sockets ƒvƒƒoƒCƒ_‚́AŽÕ’f‚³‚ꂽƒ\ƒPƒbƒg‚Ì connect ‚ÌŽg—p‚ɑΉž‚·‚é•K—v‚Í‚ ‚è‚Ü‚¹‚ñB + */ + bool shutdown(socket_t s, int how=3) + { + return _apiret_WSAle( ::shutdown(s, how) ); + } + + // close() + bool close(socket_t s) + { + return _apiret_WSAle( ::closesocket(s) ); + } + + /* + // select() + int select(socket_t s, + fdset_t *readfds, fdset_t *writefds, fdset_t *exceptfds, + long timeout_sec, long timeout_usec) + { + struct ::timeval tv; + tv.tv_sec = timeout_sec; + tv.tv_usec = timeout_usec; + + int ret = ::select(s, readfds, writefds, exceptfds, tv); + _WSAle_update(); + return ret; + } + */ + bool wait_readable(socket_t s, int timeout_ms) + { + ::fd_set readfds; + FD_ZERO(&readfds); + FD_SET(s, &readfds); + + int ret = _myselect(s, &readfds, NULL, NULL, timeout_ms/1000, timeout_ms*1000); + _WSAle_update(); + //return FD_ISSET(m_socket, &readfds); + return (ret > 0); + } + bool is_connected(socket_t s) + { + ::fd_set readfds; + FD_ZERO(&readfds); + FD_SET(s, &readfds); + + int ret = _myselect(s, &readfds, NULL, NULL, 0,0); + _WSAle_update(); + //return FD_ISSET(m_socket, &readfds); + return (ret != -1); + } + + //////////////////////////////////////////////////////////////// + + // recv + // Žw’肳‚ꂽƒ\ƒPƒbƒgƒfƒBƒXƒNƒŠƒvƒ^‚ªƒXƒgƒŠ[ƒ€ƒ\ƒPƒbƒg‚̏ꍇA + // ŠÖ”‚̓oƒbƒtƒ@‚ÉŽóMÏ‚݃f[ƒ^‚ð“ü‚ê‚ç‚ê‚邾‚¯“ü‚êA + // Žc‚è‚̃f[ƒ^‚ÍŽŸ‰ñ‚̌Ăяo‚µ‚Ŏ擾‚·‚鎖‚ª‚Å‚«‚Ü‚·B + // ƒf[ƒ^ƒOƒ‰ƒ€ƒ\ƒPƒbƒg‚̏ꍇ‚É‚ÍŽóM‚µ‚½ƒf[ƒ^ƒOƒ‰ƒ€‚Ì‚Å‚«‚邾‚¯‘½‚­‚ð + // ƒoƒbƒtƒ@‚É•Û‘¶‚µ‚Ü‚·‚ªAƒoƒbƒtƒ@‚É“ü‚è‚«‚ç‚È‚©‚Á‚½•ª‚Í”jŠü‚³‚ê‚Ü‚·B + // ‚±‚ÌŽžAŠÖ”‚Í WSEMSGSIZE ƒGƒ‰[‚𔭐¶‚µ‚Ü‚·B + // ‚±‚̊֐”‚Å–â‘肪”­¶‚µ‚È‚¯‚ê‚΁AŽóM‚µ‚½ƒoƒCƒg”‚ð•Ô‚µ‚Ü‚·B + // Ú‘±‚ª³í‚ɕ‚¶‚ç‚ê‚Ä‚¢‚½ê‡‚̓[ƒ‚ð•Ô‚µ‚Ü‚·B + // ƒGƒ‰[‚Í-1 + int recv(socket_t s, void* buf, int len, int flag) + { + int ret = ::recv(s, (char*)buf, len, flag); + _WSAle_update(); + if ( ret == SOCKET_ERROR ) + return -1; + return ret; + } + + // send() + // ŠÖ”ŒÄ‚яo‚µŒã‚·‚®‚Ƀf[ƒ^‚ª‘—M‚³‚ê‚é‚ÆŒ¾‚¤•ÛØ‚Í‚ ‚è‚Ü‚¹‚ñB + // ‚à‚µ‘—Mƒoƒbƒtƒ@‚ª‚¢‚Á‚Ï‚¢‚ŁAV‚µ‚¢ƒf[ƒ^‚ðƒoƒbƒtƒ@‚É•Û‘¶‚Å‚«‚È‚¢ê‡A + // ŠÖ”‚Í•Û‘¶‚ª‰Â”\‚É‚È‚é‚܂ŏˆ—‚ð’†’f‚µ‚Ü‚·B + // ‚±‚̊֐”‚Å–â‘肪”­¶‚µ‚È‚¯‚ê‚΁A‘—M‚µ‚½‘SƒoƒCƒg”‚ð•Ô‚µ‚Ü‚·B + // ƒGƒ‰[‚Í-1 + int send(socket_t s, const char* buf, int len, int flag) + { + int ret = ::send(s, buf, len, flag); + _WSAle_update(); + if ( ret == SOCKET_ERROR ) + return -1; + return ret; + } + + //////////////////////////////////////////////////////////////////// + + int get_last_error(){ return m_last_error; } + const char* get_last_error_msg() + { + m_last_error_msg = ""; + char *msg_buf; + ::FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, m_last_error, LANG_USER_DEFAULT, (LPSTR)&msg_buf, 0, NULL ); + if ( msg_buf != NULL ){ + m_last_error_msg = msg_buf; + LocalFree(msg_buf); + } + return m_last_error_msg.c_str(); + } + + bool is_invalid_socket(::SOCKET s){ + return ( s == invalid_socket ? true : false ); + } + bool is_valid_socket(::SOCKET s){ + return ( s == invalid_socket ? false : true ); + } + }; + typedef socket_windows_impl_<> socket_windows_impl; + + //static int m_instance_count = 0; +} + +#endif//__SFJP_ROAST__windows__net__socket_windows_impl_HPP__