1 // SmartSock.cpp: CSmartSock クラスのインプリメンテーション
3 //////////////////////////////////////////////////////////////////////
13 //#pragma warning(disable: 4101) // warning C4101: "ローカル変数は 1 度も使われていません。"
14 //#pragma warning(disable: 4996) // warning C4996: "This function or variable may be unsafe. Consider using _wsplitpath_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details"
17 //#pragma comment(lib, "WS2_32")
20 //////////////////////////////////////////////////////////////////////
22 //////////////////////////////////////////////////////////////////////
24 #define CHECK_FREESOCK(R) if(m_Socket != INVALID_SOCKET){m_dwLastError = EC_SOCKINVALID; return (R);}
25 #define CHECK_TCPSOCK(R) if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_TCP)){m_dwLastError = EC_SOCKINVALID; return (R);}
26 #define CHECK_UDPSOCK(R) if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_UDP)){m_dwLastError = EC_SOCKINVALID; return (R);}
29 //////////////////////////////////////////////////////////////////////
31 //////////////////////////////////////////////////////////////////////
33 DWORD CSmartSock::dwInstanceNum = 0UL;
35 CSmartSock::CSmartSock()
36 : m_Socket(INVALID_SOCKET)
37 , m_bSockType(SOCKTYPE_NON)
38 , m_dwLastError(EC_NOERROR)
41 if(!(dwInstanceNum++))InitWinSock2();
44 CSmartSock::~CSmartSock()
49 if(!(--dwInstanceNum))FreeWinSock2();
52 const BOOL CSmartSock::Connect(LPCTSTR lpszHost, const WORD wPort, const DWORD dwTimeOut)
54 CHECK_FREESOCK(FALSE);
57 m_dwLastError = EC_PARAMINVALID;
62 const DWORD dwIP = HostToIP(lpszHost);
64 if(dwIP == INADDR_NONE){
65 m_dwLastError = EC_SOCKERROR;
69 return Connect(dwIP, wPort, dwTimeOut);
72 const BOOL CSmartSock::Connect(const DWORD dwIP, const WORD wPort, const DWORD dwTimeOut)
74 CHECK_FREESOCK(FALSE);
77 if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
78 m_dwLastError = EC_SOCKERROR;
84 SockAddr.sin_family = AF_INET;
85 SockAddr.sin_port = htons(wPort);
86 SockAddr.sin_addr.s_addr = htonl(dwIP);
90 if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr))){
92 m_dwLastError = EC_SOCKERROR;
96 m_dwLastError = EC_NOERROR;
103 struct timeval TimeVal;
104 TimeVal.tv_sec = 10UL;
105 TimeVal.tv_usec = 0UL;
106 nArg = fcntl(m_Socket, F_GETFL, 0);
108 FD_SET(m_Socket, &FdSet);
112 if(::fcntl(m_Socket, F_SETFL, nArg | O_NONBLOCK) == SOCKET_ERROR)throw (const DWORD)__LINE__;
115 if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr)) != SOCKET_ERROR)throw (const DWORD)__LINE__;
117 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINPROGRESS)throw (const DWORD)__LINE__;
120 if(!::select(32, NULL, &FdSet, NULL, &TimeVal))throw (const DWORD)__LINE__;
123 if(!FD_ISSET(m_Socket, &FdSet)){
125 m_dwLastError = EC_TIMEOUT;
130 if(::fcntl(m_Socket, F_SETFL, nArg) == SOCKET_ERROR)throw (const DWORD)__LINE__;
132 catch(const DWORD dwLine){
135 m_dwLastError = EC_SOCKERROR;
139 m_bSockType = SOCKTYPE_TCP;
140 m_dwLastError = EC_NOERROR;
145 const BOOL CSmartSock::Listen(const WORD wPort)
147 CHECK_FREESOCK(FALSE);
150 if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
151 m_dwLastError = EC_SOCKERROR;
156 SOCKADDR_IN SockAddr;
157 SockAddr.sin_family = AF_INET;
158 SockAddr.sin_port = htons(wPort);
159 SockAddr.sin_addr.s_addr = INADDR_ANY;
164 setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
167 if(::bind(m_Socket, (PSOCKADDR)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR)throw (const DWORD)__LINE__;
170 if(::listen(m_Socket, 5) == SOCKET_ERROR)throw (const DWORD)__LINE__;
172 catch(const DWORD dwLine){
175 m_dwLastError = EC_SOCKERROR;
179 m_bSockType = SOCKTYPE_TCP;
180 m_dwLastError = EC_NOERROR;
185 CSmartSock * CSmartSock::Accept(void)
187 CHECK_TCPSOCK(FALSE);
190 memset(&AddrIn, 0, sizeof(AddrIn));
191 socklen_t iAddrLen = sizeof(AddrIn);
194 SOCKET SockIn = ::accept(m_Socket, (sockaddr *)&AddrIn, &iAddrLen);
196 if(SockIn == INVALID_SOCKET){
198 m_dwLastError = EC_SOCKERROR;
202 CSmartSock *pNewSock = new CSmartSock;
203 pNewSock->m_Socket = SockIn;
204 pNewSock->m_bSockType = SOCKTYPE_TCP;
206 m_dwLastError = EC_NOERROR;
211 const BOOL CSmartSock::Send(const BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)
213 CHECK_TCPSOCK(FALSE);
215 if(!pBuff || !dwLen){
216 m_dwLastError = EC_PARAMINVALID;
221 DWORD dwRef = 0UL, dwSend = 0UL;
224 dwRef = SendOnce(pBuff + dwSend, dwLen - dwSend, dwTimeOut);
225 if(!dwRef) return FALSE;
227 while((dwSend += dwRef) < dwLen);
232 const BOOL CSmartSock::Recv(BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)
234 CHECK_TCPSOCK(FALSE);
236 if(!pBuff || !dwLen){
237 m_dwLastError = EC_PARAMINVALID;
242 DWORD dwRef = 0UL, dwRecv = 0UL;
245 if(!(dwRef = RecvOnce(pBuff + dwRecv, dwLen - dwRecv, dwTimeOut)))return FALSE;
247 while((dwRecv += dwRef) < dwLen);
252 const DWORD CSmartSock::SendOnce(const BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)
256 if(!pBuff || !dwMaxLen){
257 m_dwLastError = EC_PARAMINVALID;
262 struct timeval stTimeOut;
264 stTimeOut.tv_sec = 10UL;
265 stTimeOut.tv_usec = 0UL;
266 if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){
268 m_dwLastError = EC_SOCKERROR;
273 const int iRef = ::send(m_Socket, (const char *)pBuff, dwMaxLen, 0);
275 if((iRef == SOCKET_ERROR) || !iRef){
276 if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){
277 m_dwLastError = EC_TIMEOUT;
282 m_dwLastError = EC_SOCKERROR;
287 m_dwLastError = EC_NOERROR;
292 const DWORD CSmartSock::RecvOnce(BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)
296 if(!pBuff || !dwMaxLen){
297 m_dwLastError = EC_PARAMINVALID;
302 struct timeval stTimeOut;
304 stTimeOut.tv_sec = 10UL;
305 stTimeOut.tv_usec = 0UL;
306 if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){
308 m_dwLastError = EC_SOCKERROR;
313 int iRef = ::recv(m_Socket, (char *)pBuff, dwMaxLen, 0);
317 m_dwLastError = EC_SOCKERROR;
321 if( iRef == SOCKET_ERROR ){
322 if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){
323 m_dwLastError = EC_TIMEOUT;
328 m_dwLastError = EC_SOCKERROR;
333 m_dwLastError = EC_NOERROR;
338 const BOOL CSmartSock::GetLocalAddr(DWORD *pdwIP, WORD *pwPort)
340 CHECK_TCPSOCK(FALSE);
342 struct sockaddr_in LocalAddr;
343 socklen_t AddrLen = sizeof(LocalAddr);
346 if(::getsockname(m_Socket, (struct sockaddr *)&LocalAddr, &AddrLen) == SOCKET_ERROR){
347 m_dwLastError = EC_SOCKERROR;
351 if(pdwIP)*pdwIP = htonl(LocalAddr.sin_addr.s_addr);
352 if(pwPort)*pwPort = ntohs(LocalAddr.sin_port);
354 m_dwLastError = EC_NOERROR;
359 const BOOL CSmartSock::GetPeerAddr(DWORD *pIP, WORD *pPort)
361 CHECK_TCPSOCK(FALSE);
363 struct sockaddr_in PeerAddr;
364 socklen_t AddrLen = sizeof(PeerAddr);
367 if(::getpeername(m_Socket, (struct sockaddr *)&PeerAddr, &AddrLen) == SOCKET_ERROR){
368 m_dwLastError = EC_SOCKERROR;
372 if(pIP)*pIP = htonl(PeerAddr.sin_addr.s_addr);
373 if(pPort)*pPort = ntohs(PeerAddr.sin_port);
375 m_dwLastError = EC_NOERROR;
380 const BOOL CSmartSock::Bind()
382 CHECK_FREESOCK(FALSE);
385 if((m_Socket = ::socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET){
386 m_dwLastError = EC_SOCKERROR;
391 SOCKADDR_IN SockAddr;
392 SockAddr.sin_family = AF_INET;
393 SockAddr.sin_port = 0U;
394 SockAddr.sin_addr.s_addr = INADDR_ANY;
397 if(::bind(m_Socket, (struct sockaddr *)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR){
399 m_dwLastError = EC_SOCKERROR;
403 m_dwLastError = EC_NOERROR;
404 m_bSockType = SOCKTYPE_UDP;
409 const DWORD CSmartSock::SendTo(const DWORD dwIP, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)
413 if(!pBuff || !dwLen){
414 m_dwLastError = EC_PARAMINVALID;
419 SOCKADDR_IN SockAddr;
420 SockAddr.sin_family = AF_INET;
421 SockAddr.sin_port = htons(wPort);
422 SockAddr.sin_addr.s_addr = htonl(dwIP);
425 int iSend = sendto(m_Socket, (const char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, sizeof(SockAddr));
427 if(iSend == SOCKET_ERROR){
428 m_dwLastError = EC_SOCKERROR;
432 m_dwLastError = EC_NOERROR;
437 const DWORD CSmartSock::SendTo(LPCTSTR lpszHost, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)
441 if(!lpszHost || !pBuff || !dwLen){
442 m_dwLastError = EC_PARAMINVALID;
447 const DWORD dwIP = HostToIP(lpszHost);
449 if(dwIP == INADDR_NONE){
450 m_dwLastError = EC_SOCKERROR;
454 return SendTo(dwIP, wPort, pBuff, dwLen);
457 const DWORD CSmartSock::RecvFrom(BYTE *pBuff, const DWORD dwLen, DWORD *pdwIP, WORD *pwPort)
461 if(!pBuff || !dwLen){
462 m_dwLastError = EC_PARAMINVALID;
467 socklen_t iSockSize = sizeof(SOCKADDR_IN);
468 SOCKADDR_IN SockAddr;
469 SockAddr.sin_family = AF_INET;
470 SockAddr.sin_port = 0U;
471 SockAddr.sin_addr.s_addr = 0UL;
474 const int iRecv = ::recvfrom(m_Socket, (char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, &iSockSize);
476 if(iRecv == SOCKET_ERROR){
477 m_dwLastError = EC_SOCKERROR;
481 if(pdwIP)*pdwIP = SockAddr.sin_addr.s_addr;
482 if(pwPort)*pwPort = ntohs(SockAddr.sin_port);
484 m_dwLastError = EC_NOERROR;
489 const BOOL CSmartSock::Close()
492 if(m_Socket != INVALID_SOCKET){
493 if(m_bSockType == SOCKTYPE_TCP){
495 ::shutdown(m_Socket, SD_BOTH);
496 while(::recv(m_Socket, &byData, 1, 0) == 1);
500 m_Socket = INVALID_SOCKET;
503 m_bSockType = SOCKTYPE_NON;
504 m_dwLastError = EC_NOERROR;
509 const DWORD CSmartSock::HostToIP(LPCTSTR lpszHost)
512 char szHost[1024] = {"\0"};
513 ::wcstombs(szHost, lpszHost, sizeof(szHost) - 1);
515 LPCSTR szHost = lpszHost;
519 const DWORD dwIP = ::inet_addr(szHost);
521 if(dwIP == INADDR_NONE){
522 struct hostent *pHost = ::gethostbyname(szHost);
526 else return *((DWORD *)pHost->h_addr_list[0]);
528 else return htonl(dwIP);
531 const DWORD CSmartSock::IPToHost(LPTSTR lpszHost, const DWORD dwIP)
533 if(!lpszHost)return FALSE;
536 const DWORD dwNetIP = htonl(dwIP);
537 struct hostent *pHost = ::gethostbyaddr((const char *)&dwNetIP, sizeof(dwNetIP), AF_INET);
538 if(!pHost)return FALSE;
541 ::mbstowcs(lpszHost, pHost->h_name, ::lstrlenA(pHost->h_name));
543 ::strcpy(lpszHost, pHost->h_name);
546 return ::strlen(lpszHost);
549 const DWORD CSmartSock::GetLastError() const
552 return m_dwLastError;
555 const BOOL CSmartSock::InitWinSock2(void)
558 ::setlocale(LC_ALL, "japanese");
564 if(::WSAStartup(MAKEWORD(2, 2), &WsaData))return FALSE;
566 if((LOBYTE(WsaData.wVersion) != 2U) || (HIBYTE(WsaData.wVersion) != 2U))return FALSE;
571 const BOOL CSmartSock::FreeWinSock2(void)
575 return (::WSACleanup())? TRUE : FALSE;