1 // SmartSock.cpp: CSmartSock
\83N
\83\89\83X
\82Ì
\83C
\83\93\83v
\83\8a\83\81\83\93\83e
\81[
\83V
\83\87\83\93\r
3 //////////////////////////////////////////////////////////////////////
\r
5 #include "SmartSock.h"
\r
7 #include <sys/time.h>
\r
10 #define new DEBUG_NEW
\r
13 //#pragma warning(disable: 4101) // warning C4101: "
\83\8d\81[
\83J
\83\8b\95Ï
\90\94\82Í 1
\93x
\82à
\8eg
\82í
\82ê
\82Ä
\82¢
\82Ü
\82¹
\82ñ
\81B"
\r
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"
\r
17 //#pragma comment(lib, "WS2_32")
\r
20 //////////////////////////////////////////////////////////////////////
\r
21 //
\83}
\83N
\83\8d\92è
\8b`
\r
22 //////////////////////////////////////////////////////////////////////
\r
24 #define CHECK_FREESOCK(R) if(m_Socket != INVALID_SOCKET){m_dwLastError = EC_SOCKINVALID; return (R);}
\r
25 #define CHECK_TCPSOCK(R) if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_TCP)){m_dwLastError = EC_SOCKINVALID; return (R);}
\r
26 #define CHECK_UDPSOCK(R) if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_UDP)){m_dwLastError = EC_SOCKINVALID; return (R);}
\r
29 //////////////////////////////////////////////////////////////////////
\r
30 //
\8d\
\92z/
\8fÁ
\96Å
\r
31 //////////////////////////////////////////////////////////////////////
\r
33 DWORD CSmartSock::dwInstanceNum = 0UL;
\r
35 CSmartSock::CSmartSock()
\r
36 : m_Socket(INVALID_SOCKET)
\r
37 , m_bSockType(SOCKTYPE_NON)
\r
38 , m_dwLastError(EC_NOERROR)
\r
40 // WinSock2
\8f\89\8aú
\89»
\r
41 if(!(dwInstanceNum++))InitWinSock2();
\r
44 CSmartSock::~CSmartSock()
\r
49 if(!(--dwInstanceNum))FreeWinSock2();
\r
52 const BOOL CSmartSock::Connect(LPCTSTR lpszHost, const WORD wPort, const DWORD dwTimeOut)
\r
54 CHECK_FREESOCK(FALSE);
\r
57 m_dwLastError = EC_PARAMINVALID;
\r
61 //
\83A
\83h
\83\8c\83X
\96¼
\82©
\82çIP
\83A
\83h
\83\8c\83X
\8eæ
\93¾
\r
62 const DWORD dwIP = HostToIP(lpszHost);
\r
64 if(dwIP == INADDR_NONE){
\r
65 m_dwLastError = EC_SOCKERROR;
\r
69 return Connect(dwIP, wPort, dwTimeOut);
\r
72 const BOOL CSmartSock::Connect(const DWORD dwIP, const WORD wPort, const DWORD dwTimeOut)
\r
74 CHECK_FREESOCK(FALSE);
\r
76 //
\83\
\83P
\83b
\83g
\8dì
\90¬
\r
77 if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
\r
78 m_dwLastError = EC_SOCKERROR;
\r
82 //
\83A
\83h
\83\8c\83X
\90Ý
\92è
\r
83 SOCKADDR_IN SockAddr;
\r
84 SockAddr.sin_family = AF_INET;
\r
85 SockAddr.sin_port = htons(wPort);
\r
86 SockAddr.sin_addr.s_addr = htonl(dwIP);
\r
88 //
\93¯
\8aú
\83R
\83l
\83N
\83g
\r
90 if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr))){
\r
92 m_dwLastError = EC_SOCKERROR;
\r
96 m_dwLastError = EC_NOERROR;
\r
100 //
\94ñ
\93¯
\8aú
\83R
\83l
\83N
\83g
\r
103 struct timeval TimeVal;
\r
104 TimeVal.tv_sec = 10UL;
\r
105 TimeVal.tv_usec = 0UL;
106 nArg = fcntl(m_Socket, F_GETFL, 0);
\r
108 FD_SET(m_Socket, &FdSet);
\r
111 //
\94ñ
\93¯
\8aú
\82É
\90Ø
\82è
\91Ö
\82¦
\r
112 if(::fcntl(m_Socket, F_SETFL, nArg | O_NONBLOCK) == SOCKET_ERROR)throw (const DWORD)__LINE__;
\r
114 //
\83R
\83l
\83N
\83g
\r
115 if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr)) != SOCKET_ERROR)throw (const DWORD)__LINE__;
\r
117 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINPROGRESS)throw (const DWORD)__LINE__;
\r
119 //
\90Ú
\91±
\8a®
\97¹
\91Ò
\82¿
\r
120 if(!::select(32, NULL, &FdSet, NULL, &TimeVal))throw (const DWORD)__LINE__;
\r
122 //
\83^
\83C
\83\80\83A
\83E
\83g
\94»
\92è
\r
123 if(!FD_ISSET(m_Socket, &FdSet)){
\r
125 m_dwLastError = EC_TIMEOUT;
\r
129 //
\93¯
\8aú
\82É
\90Ø
\82è
\91Ö
\82¦
\r
130 if(::fcntl(m_Socket, F_SETFL, nArg) == SOCKET_ERROR)throw (const DWORD)__LINE__;
\r
132 catch(const DWORD dwLine){
\r
133 //
\83G
\83\89\81[
\94
\90¶
\r
135 m_dwLastError = EC_SOCKERROR;
\r
139 m_bSockType = SOCKTYPE_TCP;
\r
140 m_dwLastError = EC_NOERROR;
\r
145 const BOOL CSmartSock::Listen(const WORD wPort)
\r
147 CHECK_FREESOCK(FALSE);
\r
149 //
\83\
\83P
\83b
\83g
\8dì
\90¬
\r
150 if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
\r
151 m_dwLastError = EC_SOCKERROR;
\r
155 //
\83A
\83h
\83\8c\83X
\90Ý
\92è
\r
156 SOCKADDR_IN SockAddr;
\r
157 SockAddr.sin_family = AF_INET;
\r
158 SockAddr.sin_port = htons(wPort);
\r
159 SockAddr.sin_addr.s_addr = INADDR_ANY;
\r
162 //
\81u
\83A
\83h
\83\8c\83X
\8eg
\97p
\92\86\81v
\83G
\83\89\81[
\82ð
\89ñ
\94ð
164 setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
166 //
\83o
\83C
\83\93\83h
\r
167 if(::bind(m_Socket, (PSOCKADDR)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR)throw (const DWORD)__LINE__;
\r
169 //
\90Ú
\91±
\8eó
\82¯
\93ü
\82ê
\r
170 if(::listen(m_Socket, 5) == SOCKET_ERROR)throw (const DWORD)__LINE__;
\r
172 catch(const DWORD dwLine){
\r
173 //
\83G
\83\89\81[
\94
\90¶
\r
175 m_dwLastError = EC_SOCKERROR;
\r
179 m_bSockType = SOCKTYPE_TCP;
\r
180 m_dwLastError = EC_NOERROR;
\r
185 CSmartSock * CSmartSock::Accept(void)
\r
187 CHECK_TCPSOCK(FALSE);
\r
189 SOCKADDR_IN AddrIn;
\r
190 memset(&AddrIn, 0, sizeof(AddrIn));
\r
191 socklen_t iAddrLen = sizeof(AddrIn);
\r
193 //
\83R
\83l
\83N
\83g
\8eó
\82¯
\93ü
\82ê
\r
194 SOCKET SockIn = ::accept(m_Socket, (sockaddr *)&AddrIn, &iAddrLen);
\r
196 if(SockIn == INVALID_SOCKET){
\r
198 m_dwLastError = EC_SOCKERROR;
\r
202 CSmartSock *pNewSock = new CSmartSock;
\r
203 pNewSock->m_Socket = SockIn;
\r
204 pNewSock->m_bSockType = SOCKTYPE_TCP;
\r
206 m_dwLastError = EC_NOERROR;
\r
211 const BOOL CSmartSock::Send(const BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)
\r
213 CHECK_TCPSOCK(FALSE);
\r
215 if(!pBuff || !dwLen){
\r
216 m_dwLastError = EC_PARAMINVALID;
\r
220 //
\8ew
\92è
\83T
\83C
\83Y
\91\97\90M
\r
221 DWORD dwRef = 0UL, dwSend = 0UL;
\r
224 dwRef = SendOnce(pBuff + dwSend, dwLen - dwSend, dwTimeOut);
225 if(!dwRef) return FALSE;
\r
227 while((dwSend += dwRef) < dwLen);
\r
232 const BOOL CSmartSock::Recv(BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)
\r
234 CHECK_TCPSOCK(FALSE);
\r
236 if(!pBuff || !dwLen){
\r
237 m_dwLastError = EC_PARAMINVALID;
\r
241 //
\8ew
\92è
\83T
\83C
\83Y
\8eó
\90M
\r
242 DWORD dwRef = 0UL, dwRecv = 0UL;
\r
245 if(!(dwRef = RecvOnce(pBuff + dwRecv, dwLen - dwRecv, dwTimeOut)))return FALSE;
\r
247 while((dwRecv += dwRef) < dwLen);
252 const DWORD CSmartSock::SendOnce(const BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)
\r
254 CHECK_TCPSOCK(0UL);
\r
256 if(!pBuff || !dwMaxLen){
\r
257 m_dwLastError = EC_PARAMINVALID;
\r
261 //
\83^
\83C
\83\80\83A
\83E
\83g
\90Ý
\92è
\r
262 struct timeval stTimeOut;
\r
264 stTimeOut.tv_sec = 10UL;
265 stTimeOut.tv_usec = 0UL;
\r
266 if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){
\r
268 m_dwLastError = EC_SOCKERROR;
273 const int iRef = ::send(m_Socket, (const char *)pBuff, dwMaxLen, 0);
\r
275 if((iRef == SOCKET_ERROR) || !iRef){
\r
276 if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){
\r
277 m_dwLastError = EC_TIMEOUT;
\r
282 m_dwLastError = EC_SOCKERROR;
\r
287 m_dwLastError = EC_NOERROR;
\r
289 return (DWORD)iRef;
\r
292 const DWORD CSmartSock::RecvOnce(BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)
\r
294 CHECK_TCPSOCK(0UL);
\r
296 if(!pBuff || !dwMaxLen){
\r
297 m_dwLastError = EC_PARAMINVALID;
\r
301 //
\83^
\83C
\83\80\83A
\83E
\83g
\92l
\90Ý
\92è
\r
302 struct timeval stTimeOut;
\r
304 stTimeOut.tv_sec = 10UL;
305 stTimeOut.tv_usec = 0UL;
\r
306 if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){
\r
308 m_dwLastError = EC_SOCKERROR;
313 int iRef = ::recv(m_Socket, (char *)pBuff, dwMaxLen, 0);
\r
315 if((iRef == SOCKET_ERROR) || !iRef){
316 if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){
317 m_dwLastError = EC_TIMEOUT;
\r
322 m_dwLastError = EC_SOCKERROR;
\r
327 m_dwLastError = EC_NOERROR;
\r
329 return (DWORD)iRef;
\r
332 const BOOL CSmartSock::GetLocalAddr(DWORD *pdwIP, WORD *pwPort)
\r
334 CHECK_TCPSOCK(FALSE);
\r
336 struct sockaddr_in LocalAddr;
\r
337 socklen_t AddrLen = sizeof(LocalAddr);
\r
339 //
\83\8d\81[
\83J
\83\8b\83A
\83h
\83\8c\83X
\8eæ
\93¾
\r
340 if(::getsockname(m_Socket, (struct sockaddr *)&LocalAddr, &AddrLen) == SOCKET_ERROR){
\r
341 m_dwLastError = EC_SOCKERROR;
\r
345 if(pdwIP)*pdwIP = htonl(LocalAddr.sin_addr.s_addr);
\r
346 if(pwPort)*pwPort = ntohs(LocalAddr.sin_port);
\r
348 m_dwLastError = EC_NOERROR;
\r
353 const BOOL CSmartSock::GetPeerAddr(DWORD *pIP, WORD *pPort)
\r
355 CHECK_TCPSOCK(FALSE);
\r
357 struct sockaddr_in PeerAddr;
\r
358 socklen_t AddrLen = sizeof(PeerAddr);
\r
360 //
\83s
\83A
\83A
\83h
\83\8c\83X
\8eæ
\93¾
\r
361 if(::getpeername(m_Socket, (struct sockaddr *)&PeerAddr, &AddrLen) == SOCKET_ERROR){
\r
362 m_dwLastError = EC_SOCKERROR;
\r
366 if(pIP)*pIP = htonl(PeerAddr.sin_addr.s_addr);
\r
367 if(pPort)*pPort = ntohs(PeerAddr.sin_port);
\r
369 m_dwLastError = EC_NOERROR;
\r
374 const BOOL CSmartSock::Bind()
\r
376 CHECK_FREESOCK(FALSE);
\r
378 // UDP
\83\
\83P
\83b
\83g
\8dì
\90¬
\r
379 if((m_Socket = ::socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET){
\r
380 m_dwLastError = EC_SOCKERROR;
\r
384 //
\83A
\83h
\83\8c\83X
\90Ý
\92è
\r
385 SOCKADDR_IN SockAddr;
\r
386 SockAddr.sin_family = AF_INET;
\r
387 SockAddr.sin_port = 0U;
\r
388 SockAddr.sin_addr.s_addr = INADDR_ANY;
\r
390 //
\83o
\83C
\83\93\83h
\r
391 if(::bind(m_Socket, (struct sockaddr *)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR){
\r
393 m_dwLastError = EC_SOCKERROR;
\r
397 m_dwLastError = EC_NOERROR;
\r
398 m_bSockType = SOCKTYPE_UDP;
\r
403 const DWORD CSmartSock::SendTo(const DWORD dwIP, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)
\r
405 CHECK_UDPSOCK(0UL);
\r
407 if(!pBuff || !dwLen){
\r
408 m_dwLastError = EC_PARAMINVALID;
\r
412 //
\83A
\83h
\83\8c\83X
\90Ý
\92è
\r
413 SOCKADDR_IN SockAddr;
\r
414 SockAddr.sin_family = AF_INET;
\r
415 SockAddr.sin_port = htons(wPort);
\r
416 SockAddr.sin_addr.s_addr = htonl(dwIP);
\r
419 int iSend = sendto(m_Socket, (const char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, sizeof(SockAddr));
\r
421 if(iSend == SOCKET_ERROR){
\r
422 m_dwLastError = EC_SOCKERROR;
\r
426 m_dwLastError = EC_NOERROR;
\r
428 return (DWORD)iSend;
\r
431 const DWORD CSmartSock::SendTo(LPCTSTR lpszHost, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)
\r
433 CHECK_UDPSOCK(0UL);
\r
435 if(!lpszHost || !pBuff || !dwLen){
\r
436 m_dwLastError = EC_PARAMINVALID;
\r
440 //
\83A
\83h
\83\8c\83X
\96¼
\82©
\82çIP
\83A
\83h
\83\8c\83X
\8eæ
\93¾
\r
441 const DWORD dwIP = HostToIP(lpszHost);
\r
443 if(dwIP == INADDR_NONE){
\r
444 m_dwLastError = EC_SOCKERROR;
\r
448 return SendTo(dwIP, wPort, pBuff, dwLen);
\r
451 const DWORD CSmartSock::RecvFrom(BYTE *pBuff, const DWORD dwLen, DWORD *pdwIP, WORD *pwPort)
\r
453 CHECK_UDPSOCK(0UL);
\r
455 if(!pBuff || !dwLen){
\r
456 m_dwLastError = EC_PARAMINVALID;
\r
460 //
\83A
\83h
\83\8c\83X
\90Ý
\92è
\r
461 socklen_t iSockSize = sizeof(SOCKADDR_IN);
\r
462 SOCKADDR_IN SockAddr;
\r
463 SockAddr.sin_family = AF_INET;
\r
464 SockAddr.sin_port = 0U;
\r
465 SockAddr.sin_addr.s_addr = 0UL;
\r
468 const int iRecv = ::recvfrom(m_Socket, (char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, &iSockSize);
\r
470 if(iRecv == SOCKET_ERROR){
\r
471 m_dwLastError = EC_SOCKERROR;
\r
475 if(pdwIP)*pdwIP = SockAddr.sin_addr.s_addr;
\r
476 if(pwPort)*pwPort = ntohs(SockAddr.sin_port);
\r
478 m_dwLastError = EC_NOERROR;
\r
480 return (DWORD)iRecv;
\r
483 const BOOL CSmartSock::Close()
\r
485 //
\83\
\83P
\83b
\83g
\83N
\83\8d\81[
\83Y
\r
486 if(m_Socket != INVALID_SOCKET){
\r
487 if(m_bSockType == SOCKTYPE_TCP){
\r
489 ::shutdown(m_Socket, SD_BOTH);
\r
490 while(::recv(m_Socket, &byData, 1, 0) == 1);
\r
494 m_Socket = INVALID_SOCKET;
\r
497 m_bSockType = SOCKTYPE_NON;
\r
498 m_dwLastError = EC_NOERROR;
\r
503 const DWORD CSmartSock::HostToIP(LPCTSTR lpszHost)
\r
506 char szHost[1024] = {"\0"};
\r
507 ::wcstombs(szHost, lpszHost, sizeof(szHost) - 1);
\r
509 LPCSTR szHost = lpszHost;
\r
512 //
\83z
\83X
\83g
\96¼
\82©
\82çIP
\83A
\83h
\83\8c\83X
\8eæ
\93¾
\r
513 const DWORD dwIP = ::inet_addr(szHost);
\r
515 if(dwIP == INADDR_NONE){
\r
516 struct hostent *pHost = ::gethostbyname(szHost);
\r
518 return INADDR_NONE;
\r
520 else return *((DWORD *)pHost->h_addr_list[0]);
\r
522 else return htonl(dwIP);
\r
525 const DWORD CSmartSock::IPToHost(LPTSTR lpszHost, const DWORD dwIP)
\r
527 if(!lpszHost)return FALSE;
\r
529 // IP
\83A
\83h
\83\8c\83X
\82©
\82ç
\83z
\83X
\83g
\96¼
\8eæ
\93¾
\r
530 const DWORD dwNetIP = htonl(dwIP);
\r
531 struct hostent *pHost = ::gethostbyaddr((const char *)&dwNetIP, sizeof(dwNetIP), AF_INET);
\r
532 if(!pHost)return FALSE;
\r
535 ::mbstowcs(lpszHost, pHost->h_name, ::lstrlenA(pHost->h_name));
\r
537 ::strcpy(lpszHost, pHost->h_name);
\r
540 return ::strlen(lpszHost);
\r
543 const DWORD CSmartSock::GetLastError() const
\r
545 //
\8dÅ
\8cã
\82É
\94
\90¶
\82µ
\82½
\83G
\83\89\81[
\82ð
\95Ô
\82·
\r
546 return m_dwLastError;
\r
549 const BOOL CSmartSock::InitWinSock2(void)
\r
552 ::setlocale(LC_ALL, "japanese");
\r
557 // WinSock2
\8f\89\8aú
\89»
\r
558 if(::WSAStartup(MAKEWORD(2, 2), &WsaData))return FALSE;
\r
560 if((LOBYTE(WsaData.wVersion) != 2U) || (HIBYTE(WsaData.wVersion) != 2U))return FALSE;
\r
565 const BOOL CSmartSock::FreeWinSock2(void)
\r
568 // WinSock2
\8aJ
\95ú
\r
569 return (::WSACleanup())? TRUE : FALSE;
\r