TNB Library
TnbSocket.h
[詳解]
1#pragma once
21#include "TnbAbstractReport.h"
22#include "TnbThread.h"
23#include "TnbVector.h"
24#include "TnbIcmp.h"
25
26
27
28//TNB Library
29namespace TNB
30{
31
32
33
36
37
38
39#ifndef _TnbDOXYGEN //Document作成用シンボル
40 _SELECTANY bool s_boIsInitSock = false;
41 _SELECTANY int s_iMaxUdpDg = 0;
42#endif
43
44
45
63{
64public:
65
71 CSocketAddress(WORD portNo = 0, DWORD ipAddress = 0) : m_portNo(portNo), m_isNameMode(false)
72 {
73 m_inaddr.s_addr = ::htonl(ipAddress);
74 }
75
82 CSocketAddress(WORD portNo, LPCTSTR lpszIpAddressName) : m_portNo(portNo), m_isNameMode(true)
83 {
84 m_inaddr.s_addr = 0;
85 m_ipAddressName = lpszIpAddressName;
86 }
87
94 void Set(WORD portNo, DWORD ipAddress = 0)
95 {
96 m_isNameMode = false;
97 m_inaddr.s_addr = ::htonl(ipAddress);
98 m_ipAddressName.Empty();
99 m_portNo = portNo;
100 }
101
109 void Set(WORD portNo, LPCTSTR lpszIpAddressName)
110 {
111 m_isNameMode = true;
112 m_inaddr.s_addr = 0;
113 m_portNo = portNo;
114 m_ipAddressName = lpszIpAddressName;
115 }
116
123 void Set(const SOCKADDR_IN& sockaddr)
124 {
125 m_isNameMode = false;
126 m_inaddr = sockaddr.sin_addr;
127 m_ipAddressName.Empty();
128 m_portNo = ::ntohs(sockaddr.sin_port);
129 }
130
135 void Get(IN_ADDR& _inaddr) const
136 {
137 if ( ! m_isNameMode )
138 {
139 _inaddr = m_inaddr;
140 }
141 else
142 {
143 DWORD ad = ::inet_addr(m_ipAddressName);
144 if ( ad == INADDR_NONE )
145 {
146 // ドット形式でないとき
147 LPHOSTENT ptHost = ::gethostbyname(m_ipAddressName);
148 if ( ptHost == NULL )
149 {
150 TRACE2( "::gethostbyname(%s) error = %d\n", CStr(m_ipAddressName), ::WSAGetLastError() );
151 ad = INADDR_NONE;
152 }
153 else
154 {
155 ad = *(reinterpret_cast<DWORD*>(ptHost->h_addr));
156 }
157 }
158 _inaddr.s_addr = ad;
159 }
160 }
161
167 void Get(SOCKADDR_IN& _sockaddr) const
168 {
169 Get(_sockaddr.sin_addr);
170 _sockaddr.sin_port = ::htons(m_portNo);
171 }
172
180 CStr GetHostName(void) const
181 {
182 IN_ADDR inaddr;
183 Get(inaddr);
184 hostent* P = ::gethostbyaddr(reinterpret_cast<const char*>(&inaddr), sizeof(inaddr), AF_INET);
185 if ( P != NULL )
186 {
187 return CStr(P->h_name);
188 }
189 return _T("");
190 }
191
198 CStr GetAddressString(bool withDns = true) const
199 {
200 if ( ! m_isNameMode )
201 {
202 if ( withDns && m_inaddr.s_addr != INADDR_ANY)
203 {
204 hostent* P = ::gethostbyaddr(reinterpret_cast<const char*>(&m_inaddr), sizeof(m_inaddr), AF_INET);
205 if ( P != NULL )
206 {
207 return CStr(P->h_name);
208 }
209 }
210 return CStr(::inet_ntoa(m_inaddr));
211 }
212 else
213 {
214 return CStr(m_ipAddressName);
215 }
216 }
217
222 DWORD GetAddress(void) const
223 {
224 in_addr addr;
225 Get(addr);
226 return ::htonl(addr.s_addr);
227 }
228
233 WORD GetPortNo(void) const
234 {
235 return m_portNo;
236 }
237
243 bool IsBroadcast(void) const
244 {
245 return GetAddress() == INADDR_BROADCAST;
246 }
247
255 static DWORD htonl(DWORD hostlong)
256 {
257 return ::htonl(hostlong);
258 }
259
267 static WORD htons(WORD hostshort)
268 {
269 return ::htons(hostshort);
270 }
271
279 static DWORD ntohl(DWORD netlong)
280 {
281 return ::ntohl(netlong);
282 }
283
291 static DWORD ntohs(DWORD netshort)
292 {
293 return ::ntohl(netshort);
294 }
295
296private:
297 bool m_isNameMode;
298 IN_ADDR m_inaddr;
299 CAscii m_ipAddressName;
300 WORD m_portNo;
301};
302
303
304
322{
323 DEFSUPER(CReportEvent);
324 SOCKET m_soData;
325 class CAbstractSocket * m_pcSocket;
326public:
327
335 CSocketEvent(CAbstractSocket* pcSocket, SOCKET so, EReportEvent eEvent = ReportEvent_Non, DWORD dwError = 0);
336
345 virtual bool Send(size_t dataSize, LPCVOID lpcvData) const;
346
355 virtual DWORD GetInterfaceId(void) const
356 {
357 return static_cast<DWORD>(m_soData) | 0x80000000;
358 }
359
367 bool GetPeerName(CSocketAddress& _address) const;
368
375 bool GetSockName(CSocketAddress& _address) const;
376
381 SOCKET GetSocket(void) const
382 {
383 return m_soData;
384 }
385};
386
387
388
406{
407 DEFSUPER(CAbstractReport);
408 friend class CSocketEvent;
409public:
410
424 {
426 virtual ~IListener(void) {}
427
441 virtual bool OnSocketEvent(const CSocketEvent& ev) = 0;
442 };
443
444
445 //----------------------------
446
447
449 CAbstractSocket(void) : _super(), m_piSocketListner(NULL), m_boIsDelay(true)
450 {
451 m_lpcBuffer = new char[E_BufferSize];
452 }
453
455 virtual ~CAbstractSocket(void)
456 {
457 delete[] m_lpcBuffer;
458 }
459
466 virtual void SetSocketListener(IListener* piSocketListener)
467 {
468 m_piSocketListner = piSocketListener;
469 }
470
478 static void StartUp(void)
479 {
480 if ( s_boIsInitSock )
481 {
482 return;
483 }
484 s_boIsInitSock = true;
485 #ifndef _WIN32_WCE
486 SOCKET so = ::socket(AF_INET, SOCK_STREAM, 0);
487 if ( so != SOCKET_ERROR )
488 {
489 ::closesocket(so);
490 return;
491 }
492 if ( ::WSAGetLastError() == WSANOTINITIALISED )
493 #endif //_WIN32_WCE
494 {
495 WSADATA wsaData;
496 if ( ::WSAStartup(E_DefaultVersion, &wsaData) == SOCKET_ERROR )
497 {
498 ASSERT1( false, "WSAStartup", "error = %d\n", ::WSAGetLastError() );
499 }
500 else
501 {
502 static CCleanup s_cleanup; // Cleanup用インスタンス
503 if ( LOBYTE(wsaData.wVersion) == 1 )
504 {
505 s_iMaxUdpDg = wsaData.iMaxUdpDg;
506 }
507 else
508 {
509 s_iMaxUdpDg = 0;
510 }
511 }
512 }
513 }
514
521 {
522 CDwordVector v;
523 CAscii na;
524 ::gethostname(na.GetBuffer(1000), 1000);
525 na.ReleaseBuffer();
526 hostent* pHostEnt = ::gethostbyname(na);
527 if ( pHostEnt != NULL )
528 {
529 loop ( i, 1000 )
530 {
531 DWORD* p = reinterpret_cast<DWORD*>(pHostEnt->h_addr_list[i]);
532 if ( p == NULL )
533 {
534 break;
535 }
536 v.Add(SwapEndian(*p));
537 }
538 }
539 return v;
540 }
541
542protected:
543
544 #ifndef _TnbDOXYGEN //Document作成用シンボル
545
547 struct TSockAddr : SOCKADDR_IN
548 {
550 void Init(void) { memset(this, 0, sizeof(SOCKADDR_IN)); }
552 static int GetSize(void) { return sizeof(SOCKADDR_IN); }
554 operator LPSOCKADDR(void) { return reinterpret_cast<LPSOCKADDR>(this); }
555 };
556
557 enum
558 {
559 #ifdef _TnbWINSOCK2_ENABLE
560 E_DefaultVersion = WINSOCK_VERSION,
561 #else
562 E_DefaultVersion = MAKEWORD(1, 1),
563 #endif
564 E_BufferSize = 10000,
565 E_RetryDelay = 2000,
566 E_SelectTimeout = 2000,
567 E_ConnectTimeout = 2000,
568 };
569 TSockAddr m_sockaddrPartner;
570 IListener * m_piSocketListner;
571 char * m_lpcBuffer;
572 bool m_boIsDelay;
573
575 class CCleanup
576 {
577 public:~CCleanup(void) { ::WSACleanup(); }
578 };
579
587 static bool ms_AddressToIp(IN_ADDR& _addr, LPCTSTR lpszAddress)
588 {
589 StartUp();
590 CSocketAddress a(0, lpszAddress);
591 a.Get(_addr);
592 return (_addr.s_addr != INADDR_NONE);
593 }
594
603 bool m_SetAddress(LPCTSTR lpszAddress, WORD wPortNo)
604 {
605 // ソケット構造体の初期化
606 m_sockaddrPartner.Init();
607 m_sockaddrPartner.sin_family = AF_INET; // TCP/IPを指定
608 CSocketAddress a(wPortNo, lpszAddress);
609 a.Get(m_sockaddrPartner);
610 return m_sockaddrPartner.sin_addr.s_addr != INADDR_NONE;
611 }
612
620 bool m_SetAddress(const CSocketAddress& address)
621 {
622 // ソケット構造体の初期化
623 m_sockaddrPartner.Init();
624 m_sockaddrPartner.sin_family = AF_INET; // TCP/IPを指定
625 address.Get(m_sockaddrPartner);
626 return m_sockaddrPartner.sin_addr.s_addr != INADDR_NONE;
627 }
628
636 bool m_Recv(SOCKET so)
637 {
638 int iLen = ::recv(so, m_lpcBuffer, E_BufferSize, 0);
639 if ( iLen == SOCKET_ERROR )
640 {
641 int iError = ::WSAGetLastError();
642 TRACE2( "::recv(%d) error = %d\n", so, iError );
643 if ( iError != WSAENOTSOCK/*10038*/ && iError != WSAESHUTDOWN/*10058*/ )
644 {
645 m_OnSocketEvent(CSocketEvent(this, so, ReportEvent_Error, iError));
646 }
647 return false; //切断
648 }
649 else if ( iLen == 0 )
650 {
651 TTRACE0("CSocket:Closed Connection\n");
652 return false;
653 }
654 else
655 {
656 CSocketEvent s(this, so);
657 s.SetData(iLen, m_lpcBuffer);
658 if ( ! m_OnSocketEvent(s) )
659 {
660 return false; //切断
661 }
662 }
663 return true;
664 }
665
673 static bool ms_SetDelayMode(SOCKET so, bool boIsDelay)
674 {
675 BOOL boValue = ! boIsDelay;
676 int iRc = ::setsockopt(
677 so,
678 IPPROTO_TCP,
679 TCP_NODELAY,
680 reinterpret_cast<const char*>(&boValue),
681 sizeof(BOOL));
682 #ifdef _DEBUG
683 if ( iRc != 0) { TRACE2( "::setsockopt(%d) error = %d\n ", so, ::WSAGetLastError()); }
684 #endif
685 {
686 BOOL yes = TRUE;
687 ::setsockopt(so, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&yes), sizeof(yes));
688 }
689 return iRc == 0;
690 }
691
700 virtual bool m_Send(SOCKET so, size_t dataSize, LPCVOID lpcvData)
701 {
702 if ( so == INVALID_SOCKET )
703 {
704 return false;
705 }
706 int iRc = ::send(so, static_cast<const char*>(lpcvData), ToInt(dataSize), 0);
707 TRACE2("::send(%u) result = %d\n", dataSize, iRc);
708 return iRc == ToInt(dataSize);
709 }
710
718 virtual bool m_GetPeerName(CSocketAddress& _address, SOCKET so)
719 {
720 TSockAddr addr;
721 int iLen = addr.GetSize();
722 if ( ::getpeername(so, addr, &iLen) == SOCKET_ERROR )
723 {
724 TRACE2( "::getpeername(%d) error = %d\n", so, ::WSAGetLastError() );
725 return false;
726 }
727 _address.Set(addr);
728 return true;
729 }
730
737 virtual bool m_OnSocketEvent(CSocketEvent& e)
738 {
739 bool r = true;
740 if ( m_piSocketListner != NULL )
741 {
742 r &= m_piSocketListner->OnSocketEvent(e);
743 }
744 r &= _super::m_OnEvent(e);
745 return r;
746 }
747
752 WORD m_GetMaxUdpDg(SOCKET s)
753 {
754 ASSERTLIB(s_iMaxUdpDg >= 0);
755 #ifdef _TnbWINSOCK2_ENABLE
756 if ( s_iMaxUdpDg == 0 )
757 {
758 int iOptVal;
759 int iOptLen = sizeof(iOptVal);
760 int r = ::getsockopt(s, SOL_SOCKET, SO_MAX_MSG_SIZE, reinterpret_cast<char*>(&iOptVal), &iOptLen);
761 return static_cast<WORD>((r == SOCKET_ERROR) ? 0 : iOptVal);
762 }
763 #endif
764 return static_cast<WORD>(s_iMaxUdpDg);
765 }
766 #endif // _TnbDOXYGEN
767};
768
769
770
772inline CSocketEvent::CSocketEvent(CAbstractSocket* pcSocket, SOCKET so, EReportEvent eEvent, DWORD dwError)
773 : _super(static_cast<IReport*>(pcSocket), eEvent, dwError)
774{
775 m_soData = so;
776 m_pcSocket = pcSocket;
777}
778
779// データ送信
780inline bool CSocketEvent::Send(size_t dataSize, LPCVOID lpcvData) const
781{
782 return m_pcSocket->Send(dataSize, lpcvData);
783// return m_pcSocket->m_Send(m_soData, dataSize, lpcvData);
784}
785
786//情報取得
787inline bool CSocketEvent::GetPeerName(CSocketAddress& _address) const
788{
789 return m_pcSocket->m_GetPeerName(_address, m_soData);
790}
791
792//情報取得
793inline bool CSocketEvent::GetSockName(CSocketAddress& _address) const
794{
795 CAbstractSocket::TSockAddr addr;
796 int iLen = addr.GetSize();
797 if ( ::getsockname(m_soData, addr, &iLen) == SOCKET_ERROR )
798 {
799 TRACE2( "::getpeername(%d) error = %d\n", m_soData, ::WSAGetLastError() );
800 return false;
801 }
802 _address.Set(addr);
803 return true;
804}
805
806
807
841{
842 DEFSUPER(CAbstractSocket);
843public:
844
851 explicit CSocketClient(bool isAutoReconnect = true)
852 : _super(), m_soData(INVALID_SOCKET), m_isAutoReconnect(isAutoReconnect), m_wServerPortNo(0)
853 {
854 m_threadReceiver.SetRunner(this);
855 }
856
858 virtual ~CSocketClient(void)
859 {
860 m_CloseDataSocket();
861 m_threadReceiver.Stop();
862 }
863
870 void SetDelayMode(bool boIsDelay)
871 {
872 m_boIsDelay = boIsDelay;
873 }
874
880 virtual CStr GetReportName(void) const
881 {
882 return CStr::Fmt(_T("SocketClient[%u]:"), m_soData);
883 }
884
891 virtual DWORD GetReportID(void) const
892 {
893 return TNBVIW_KIND_SOCK_C + (m_soData & 0xFFFF);
894 }
895
901 SOCKET GetSocket(void) const
902 {
903 return m_soData;
904 }
905
910 void SetServer(const CSocketAddress& address)
911 {
912 StartUp();
913 Stop();
914 m_strServerAddress = address.GetAddressString(false);
915 m_wServerPortNo = address.GetPortNo();
916 }
917
924 virtual bool Start(void)
925 {
926 StartUp();
927 Stop();
928 if ( ! m_SetAddress(m_strServerAddress, m_wServerPortNo) )
929 {
930 if ( ! m_isAutoReconnect )
931 {
932 return false;
933 }
934 }
935 if ( ! m_isAutoReconnect )
936 {
937 if ( ! m_ConnectSub() )
938 {
939 return false;
940 }
941 }
942 #ifdef _DEBUG
943 m_threadReceiver.Start(CStr::Fmt(_T("Client(p=%d)監視"), m_wServerPortNo));
944 #else
945 m_threadReceiver.Start();
946 #endif
947 return true;
948 }
949
957 bool Connect(const CSocketAddress& address)
958 {
959 SetServer(address);
960 return Start();
961 }
962
969 virtual bool IsAlive(void) const
970 {
971 return m_threadReceiver.IsAlive();
972 }
973
979 virtual bool IsConnect(void) const
980 {
981 return m_soData != INVALID_SOCKET;
982 }
983
991 virtual bool Send(size_t dataSize, LPCVOID lpcvData)
992 {
993 TTRACE1("CSocket[Client%d]:Send\n", m_soData);
994 _super::m_OnSend(dataSize, lpcvData);
995 return m_Send(m_soData, dataSize, lpcvData);
996 }
997
1001 virtual void Stop(void)
1002 {
1003 if ( IsConnect() )
1004 {
1005 m_CloseDataSocket();
1006 }
1007 m_threadReceiver.Stop();
1008 }
1009
1013 void Disconnect(void)
1014 {
1015 Stop();
1016 }
1017
1023 {
1024 return m_threadReceiver;
1025 }
1026
1027#ifndef _TnbDOXYGEN //Document作成用シンボル
1028 // [実行] 開始. 旧タイプの指定方法です。 廃止予定です。
1029 bool Connect(LPCTSTR lpszAddress, WORD wPortNo)
1030 {
1031 SetServer(CSocketAddress(wPortNo, lpszAddress));
1032 return Start();
1033 }
1034#endif
1035
1036private:
1037 TNB::CThread m_threadReceiver;
1038 bool m_isAutoReconnect;
1039 SOCKET m_soData;
1040 CStr m_strServerAddress;
1041 WORD m_wServerPortNo;
1042
1050 bool m_ConnectWithTimeout(SOCKET so, DWORD dwTimeout)
1051 {
1052 DWORD dwOpt = 1; //非ブロッキングに設定
1053 ::ioctlsocket(so, FIONBIO, &dwOpt);
1054 int iCntRst = ::connect(so, m_sockaddrPartner, m_sockaddrPartner.GetSize());
1055 if ( iCntRst == SOCKET_ERROR )
1056 {
1057 DWORD dwError = ::WSAGetLastError();
1058 if ( dwError != WSAEWOULDBLOCK )
1059 {
1060 TRACE2("::connect(%d) error = %d\n", so, dwError);
1061 dwOpt = 0; //ブロッキングに設定
1062 ::ioctlsocket(so, FIONBIO, &dwOpt);
1063 return false;
1064 }
1065 fd_set tFdSet;
1066 FD_ZERO(&tFdSet);
1067 FD_SET(so, &tFdSet);
1068 timeval tTimeVal = { dwTimeout / 1000, dwTimeout % 1000 };
1069 ::select(FD_SETSIZE, NULL, &tFdSet, NULL, &tTimeVal);
1070 if ( ! FD_ISSET(so, &tFdSet) )
1071 {
1072 dwOpt = 0; //ブロッキングに設定
1073 ::ioctlsocket(so, FIONBIO, &dwOpt);
1074 return false;
1075 }
1076 }
1077 dwOpt = 0; //ブロッキングに設定
1078 ::ioctlsocket(so, FIONBIO, &dwOpt);
1079 return true;
1080 }
1081
1089 bool m_ConnectSub(void)
1090 {
1091 if ( m_soData != INVALID_SOCKET )
1092 {
1093 return true;
1094 }
1095 SOCKET so = ::socket(AF_INET, SOCK_STREAM, 0);
1096 if ( so == SOCKET_ERROR )
1097 {
1098 TRACE1( "::socket() error = %d\n", ::WSAGetLastError() );
1099 return false;
1100 }
1101 if ( ! ms_AddressToIp(m_sockaddrPartner.sin_addr, m_strServerAddress) )
1102 {
1103 ::shutdown(so, SD_BOTH);
1104 ::closesocket(so);
1105 return false;
1106 }
1107 if ( ! m_ConnectWithTimeout(so, E_ConnectTimeout) )
1108 {
1109 ::shutdown(so, SD_BOTH);
1110 ::closesocket(so);
1111 return false;
1112 }
1113 TTRACE1("CSocket[Client%d]:Connected\n", so);
1114 m_soData = so;
1115 if ( ! m_OnSocketEvent(CSocketEvent(this, m_soData, ReportEvent_Connect)) )
1116 {
1117 m_CloseDataSocket();
1118 return false;
1119 }
1120 ms_SetDelayMode(m_soData, m_boIsDelay);
1121 return true;
1122 }
1123
1125 void m_CloseDataSocket(void)
1126 {
1127 if ( m_soData != INVALID_SOCKET )
1128 {
1129 SOCKET so = m_soData;
1130 m_soData = INVALID_SOCKET;
1131 TTRACE1("CSocket[Client%d]:Closed\n", so);
1132 m_OnSocketEvent(CSocketEvent(this, so, ReportEvent_Disconnect));
1133 ::shutdown(so, SD_BOTH);
1134 ::closesocket(so);
1135 }
1136 }
1137
1142 virtual DWORD Run(void)
1143 {
1144 while ( IsRunnable() )
1145 {
1146 if ( ! m_ConnectSub() )
1147 {
1148 loop ( i, 20 )
1149 {
1150 if ( ! IsRunnable() )
1151 {
1152 break;
1153 }
1154 ::Sleep(E_RetryDelay / 20);
1155 }
1156 continue;
1157 }
1158 //
1159 CTickCount tickIdle;
1160 CTickCount tickConCheck;
1161 while ( IsRunnable() )
1162 {
1163 fd_set tFdSet;
1164 FD_ZERO(&tFdSet);
1165 FD_SET(m_soData, &tFdSet);
1166 int iSelTime = E_SelectTimeout;
1167 int iInterval = _super::GetIdleInterval();
1168 if ( iInterval > 0 )
1169 {
1170 iSelTime = iInterval;
1171 }
1172 timeval tTimeVal = { iSelTime / 1000, iSelTime % 1000 };
1173 ::select(ToInt(m_soData + 1), &tFdSet, NULL, NULL, &tTimeVal);
1174 if ( ! FD_ISSET(m_soData, &tFdSet) )
1175 {
1176 if ( tickConCheck.IsPassedAndReset(E_SelectTimeout) )
1177 {
1178 CSocketAddress adds;
1179 if ( ! m_GetPeerName(adds, m_soData) )
1180 {
1181 break; //切断
1182 }
1183 }
1184 if ( iInterval > 0 && tickIdle.IsPassedAndReset(iInterval) )
1185 {
1186 if ( ! m_OnSocketEvent(CSocketEvent(this, m_soData, ReportEvent_Idle)) )
1187 {
1188 break; //切断
1189 }
1190 }
1191 continue;
1192 }
1193 if ( ! m_Recv(m_soData) )
1194 {
1195 break; //切断
1196 }
1197 TTRACE1("CSocket[Client%d]:受信成功\n", m_soData);
1198 tickIdle.Reset();
1199 }
1200 //
1201 TTRACE1("CSocket[Client%d]:受信停止\n", m_soData);
1202 m_CloseDataSocket();
1203 if ( ! m_isAutoReconnect )
1204 {
1205 break;
1206 }
1207 loop ( i, 20 )
1208 {
1209 if ( ! IsRunnable() )
1210 {
1211 break;
1212 }
1213 ::Sleep(E_RetryDelay / 20);
1214 }
1215 }
1216 m_OnSocketEvent(CSocketEvent(this, m_soData, ReportEvent_End));
1217 return 0;
1218 }
1219};
1220
1221
1222
1259{
1260 DEFSUPER(CAbstractSocket);
1261public:
1262
1264 CSocketServer(void) : _super(), m_soListen(INVALID_SOCKET), m_connectMax(1), m_wOpenPortNo(0)
1265 {
1266 m_threadReceiver.SetRunner(this);
1267 }
1268
1270 virtual ~CSocketServer(void)
1271 {
1272 Close();
1273 }
1274
1281 void SetDelayMode(bool boIsDelay)
1282 {
1283 m_boIsDelay = boIsDelay;
1284 }
1285
1291 virtual CStr GetReportName(void) const
1292 {
1293 return CStr::Fmt(_T("SocketServer[%08X]:"), this);
1294 }
1295
1302 virtual DWORD GetReportID(void) const
1303 {
1304 return TNBVIW_KIND_SOCK_S + (reinterpret_cast<DWORD>(this) & 0xFFFF);
1305 }
1306
1315 void SetConnectMax(size_t max)
1316 {
1317 if ( max >= 1 )
1318 {
1319 m_connectMax = max;
1320 }
1321 }
1322
1327 void SetParameter(const CSocketAddress& address)
1328 {
1329 StartUp();
1330 Stop();
1331 m_wOpenPortNo = address.GetPortNo();
1332 m_strAwaitAddress = address.GetAddressString(false);
1333 }
1334
1342 virtual bool Start(void)
1343 {
1344 StartUp();
1345 Stop();
1346 if ( GetConnectedSockets() != 0 )
1347 {
1348 return false;
1349 }
1350 if ( m_strAwaitAddress.IsEmpty() )
1351 {
1352 m_strAwaitAddress = _T("0.0.0.0");
1353 }
1354 if ( ! m_SetAddress(m_strAwaitAddress, m_wOpenPortNo) )
1355 {
1356 return false;
1357 }
1358 if ( m_OpenListenSocket() == 10048 )
1359 {
1360 return false;
1361 }
1362 #ifdef _DEBUG
1363 m_threadReceiver.Start(CStr::Fmt(_T("Server(p=%d)監視"), m_wOpenPortNo));
1364 #else
1365 m_threadReceiver.Start();
1366 #endif
1367 return true;
1368 }
1369
1377 bool Open(const CSocketAddress& address)
1378 {
1379 SetParameter(address);
1380 return Start();
1381 }
1382
1388 INT_PTR GetConnectedSockets(CSocketVector* P = NULL) const
1389 {
1390 if ( P != NULL )
1391 {
1392 EXCLUSIVE(&m_syncSocket);
1393 *P = m_vsoData;
1394 }
1395 return m_vsoData.GetSize();
1396 }
1397
1404 bool IsConnect(SOCKET so) const
1405 {
1406 EXCLUSIVE(&m_syncSocket);
1407 loop ( i, m_vsoData.GetSize() )
1408 {
1409 if ( m_vsoData[i] == so ){ return true; }
1410 }
1411 return false;
1412 }
1413
1422 bool Send(SOCKET so, size_t dataSize, LPCVOID lpcvData)
1423 {
1424 TTRACE1("CSocket[Server%d]:Send\n", so);
1425 _super::m_OnSend(dataSize, lpcvData);
1426 return m_Send(so, dataSize, lpcvData);
1427 }
1428
1436 bool GetPeerName(CSocketAddress& _address, SOCKET so)
1437 {
1438 return m_GetPeerName(_address, so);
1439 }
1440
1445 void Disconnect(SOCKET so)
1446 {
1447 m_CloseDataSocket(so);
1448 }
1449
1456 virtual bool IsAlive(void) const
1457 {
1458 return m_threadReceiver.IsAlive();
1459 }
1460
1466 virtual bool IsConnect(void) const
1467 {
1468 return GetConnectedSockets() != 0;
1469 }
1470
1479 virtual bool Send(size_t dataSize, LPCVOID lpcvData)
1480 {
1481 TTRACE0("CSocket[Server%d]:Send<All>\n");
1482 bool boRc = true;
1483 EXCLUSIVE(&m_syncSocket);
1484 loop ( i, m_vsoData.GetSize() )
1485 {
1486 boRc &= Send(m_vsoData[i], dataSize, lpcvData);
1487 }
1488 return boRc;
1489 }
1490
1496 void Disconnect(void)
1497 {
1498 m_CloseAllDataSockets();
1499 m_OpenListenSocket();
1500 }
1501
1505 virtual void Stop(void)
1506 {
1507 Close();
1508 }
1509
1513 void Close(void)
1514 {
1515 TTRACE0("CSocket[Server]:サーバクローズ\n");
1516 m_CloseAllDataSockets();
1517 m_CloseListenSocket();
1518 m_threadReceiver.Stop();
1519 }
1520
1526 {
1527 return m_threadReceiver;
1528 }
1529
1530private:
1531 TNB::CThread m_threadReceiver;
1532 SOCKET m_soListen;
1533 CSocketVector m_vsoData;
1534 CSyncSection m_syncSocket;
1535 size_t m_connectMax;
1536 WORD m_wOpenPortNo;
1537 CStr m_strAwaitAddress;
1538
1543 void m_CloseAllDataSockets(void)
1544 {
1545 EXCLUSIVE(&m_syncSocket);
1546 size_t iLen = m_vsoData.GetSize();
1547 if ( iLen > 0 )
1548 {
1549 TTRACE0("CSocket[Server]:全クローズ\n");
1550 loop ( i, iLen )
1551 {
1552 if ( m_vsoData[i] != INVALID_SOCKET )
1553 {
1554 SOCKET so = m_vsoData[i];
1555 TTRACE1("CSocket[Server%d]:クローズ\n", so);
1556 m_OnSocketEvent(CSocketEvent(this, so, ReportEvent_Disconnect));
1557 ::shutdown(so, SD_BOTH);
1558 ::closesocket(so);
1559 }
1560 }
1561 m_vsoData.RemoveAll();
1562 }
1563 }
1564
1569 void m_CloseDataSocket(SOCKET so)
1570 {
1571 EXCLUSIVE(&m_syncSocket);
1572 loop ( i, m_vsoData.GetSize() )
1573 {
1574 if ( m_vsoData[i] == so )
1575 {
1576 TTRACE1("CSocket[Server%d]:クローズ\n", so);
1577 m_vsoData.Remove(i);
1578 m_OnSocketEvent(CSocketEvent(this, so, ReportEvent_Disconnect));
1579 ::shutdown(so, SD_BOTH);
1580 ::closesocket(so);
1581 m_OpenListenSocket();
1582 break;
1583 }
1584 }
1585 }
1586
1592 int m_OpenListenSocket(void)
1593 {
1594 if ( m_soListen == INVALID_SOCKET )
1595 {
1596 m_soListen = ::socket(AF_INET, SOCK_STREAM, 0); // TCP socket
1597 if ( m_soListen == INVALID_SOCKET )
1598 {
1599 int r = ::WSAGetLastError();
1600 ASSERT( r != 0 );
1601 TRACE1( "::socket() error = %d\n", r );
1602 return r;
1603 }
1604 if ( ::bind(m_soListen, m_sockaddrPartner, m_sockaddrPartner.GetSize()) == SOCKET_ERROR )
1605 {
1606 int r = ::WSAGetLastError();
1607 ASSERT( r != 0 );
1608 TRACE2( "::bind(%d) error = %d\n", m_soListen, r );
1609 return r;
1610 }
1611 TTRACE0("CSocket[Server]:リスナーSOCKETオープン\n");
1612 if ( ::listen(m_soListen, 5) == SOCKET_ERROR )
1613 {
1614 int r = ::WSAGetLastError();
1615 ASSERT( r != 0 );
1616 TRACE2( "::listen(%d) error = %d\n", m_soListen, r );
1617 m_CloseListenSocket();
1618 return r;
1619 }
1620 }
1621 return 0;
1622 }
1623
1625 void m_CloseListenSocket(void)
1626 {
1627 if ( m_soListen != INVALID_SOCKET )
1628 {
1629 SOCKET so = m_soListen;
1630 m_soListen = INVALID_SOCKET;
1631 TTRACE0("CSocket[Server]:リスナーSOCKETクローズ\n");
1632 ::shutdown(so, SD_BOTH);
1633 ::closesocket(so);
1634 }
1635 }
1636
1641 virtual DWORD Run(void)
1642 {
1643 while ( IsRunnable() )
1644 {
1645 if ( m_OpenListenSocket() != 0 )
1646 {
1647 loop ( i, 20 )
1648 {
1649 if ( ! IsRunnable() )
1650 {
1651 break;
1652 }
1653 ::Sleep(E_RetryDelay / 20);
1654 }
1655 continue;
1656 }
1657 //
1658 CTickCount tickIdle;
1659 CTickCount tickConCheck;
1660 while ( IsRunnable() )
1661 {
1662 fd_set tFdSet;
1663 FD_ZERO(&tFdSet);
1664 CSocketVector vsoBack;
1665 INT_PTR iConnectedCount = GetConnectedSockets(&vsoBack);
1666 if ( iConnectedCount > 0 )
1667 {
1668 loop ( i, iConnectedCount )
1669 {
1670 FD_SET(vsoBack[i], &tFdSet);
1671 }
1672 }
1673 if ( m_soListen != INVALID_SOCKET )
1674 {
1675 FD_SET(m_soListen, &tFdSet);
1676 }
1677 int iSelTime = E_SelectTimeout;
1678 int iInterval = _super::GetIdleInterval();
1679 if ( iInterval > 0 )
1680 {
1681 iSelTime = iInterval;
1682 }
1683 timeval tTimeVal = { iSelTime / 1000, iSelTime % 1000 };
1684 if ( ::select(FD_SETSIZE, &tFdSet, NULL, NULL, &tTimeVal) == SOCKET_ERROR )
1685 {
1686 DWORD dwError = ::WSAGetLastError();
1687 TRACE1( "::select() error = %d\n", dwError );
1688 if ( dwError == WSAEINVAL )
1689 {
1690 ::Sleep(E_SelectTimeout);
1691 }
1692 continue;
1693 }
1694 if ( FD_ISSET(m_soListen, &tFdSet) )
1695 {
1696 FD_CLR(m_soListen, &tFdSet);
1697 TSockAddr addrFrom;
1698 int iFromlen = addrFrom.GetSize();
1699 SOCKET so = ::accept(m_soListen, addrFrom, &iFromlen);
1700 if ( so == INVALID_SOCKET )
1701 {
1702 TRACE2( "::accept(%d) error = %d\n", m_soListen, ::WSAGetLastError() );
1703 m_CloseListenSocket();
1704 }
1705 else if ( m_vsoData.GetSize() >= m_connectMax )
1706 {
1707 TTRACE1( "CSocket[Server%d]:接続依頼、拒否\n", so );
1708 m_CloseListenSocket();
1709 ::shutdown(so, SD_BOTH);
1710 ::closesocket(so);
1711 }
1712 else
1713 {
1714 TTRACE1("CSocket[Server%d]:接続\n", so);
1715 ms_SetDelayMode(so, m_boIsDelay);
1716 {
1717 EXCLUSIVE(&m_syncSocket);
1718 m_vsoData.AddEx(so);
1719 if ( m_vsoData.GetSize() >= m_connectMax )
1720 {
1721 m_CloseListenSocket();
1722 }
1723 }
1724 if ( ! m_OnSocketEvent(CSocketEvent(this, so, ReportEvent_Connect)) )
1725 {
1726 TTRACE1("CSocket[Server%d]:切断\n", so);
1727 m_CloseDataSocket(so);
1728 m_OpenListenSocket();
1729 }
1730 }
1731 }
1732 if ( iConnectedCount == 0 )
1733 {
1734 continue;
1735 }
1736 if ( tFdSet.fd_count == 0 )
1737 {
1738 if ( tickConCheck.IsPassedAndReset(E_SelectTimeout) )
1739 {
1740 CSocketAddress adds;
1741 loop ( i, iConnectedCount )
1742 {
1743 if ( ! m_GetPeerName(adds, vsoBack[i]) )
1744 {
1745 m_CloseDataSocket(vsoBack[i]);
1746 m_OpenListenSocket();
1747 }
1748 }
1749 }
1750 if ( iInterval > 0 && tickIdle.IsPassedAndReset(iInterval) )
1751 {
1752 loop ( i, iConnectedCount )
1753 {
1754 if ( ! m_OnSocketEvent(CSocketEvent(this, vsoBack[i], ReportEvent_Idle)) )
1755 {
1756 TTRACE1("CSocket[Server%d]:切断\n", vsoBack[i]);
1757 m_CloseDataSocket(vsoBack[i]);
1758 m_OpenListenSocket();
1759 }
1760 }
1761 }
1762 continue;
1763 }
1764 //
1765 loop ( i, iConnectedCount )
1766 {
1767 if ( ! FD_ISSET(vsoBack[i], &tFdSet) )
1768 {
1769 continue;
1770 }
1771 if ( ! m_Recv(vsoBack[i]) )
1772 {
1773 TTRACE1("CSocket[Server%d]:切断(Recvによる)\n", vsoBack[i]);
1774 m_CloseDataSocket(vsoBack[i]);
1775 m_OpenListenSocket();
1776 }
1777 else
1778 {
1779 TTRACE1("CSocket[Server%d]:データ受信\n", vsoBack[i]);
1780 }
1781 }
1782 tickIdle.Reset();
1783 }
1784 }
1785 m_OnSocketEvent(CSocketEvent(this, 0, ReportEvent_End));
1786 return 0;
1787 };
1788};
1789
1790
1791
1792}; // TNB
通信関係のヘッダ
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
ICMP処理関係のヘッダ
スレッド管理関係のヘッダ
配列型情報管理関係のヘッダ
通信アクセス抽象クラス
Socket共通クラス
Definition: TnbSocket.h:406
static void StartUp(void)
[設定] SOCKET初期化.
Definition: TnbSocket.h:478
virtual ~CAbstractSocket(void)
デストラクタ
Definition: TnbSocket.h:455
friend class CSocketEvent
フレンドクラス定義
Definition: TnbSocket.h:408
static CDwordVector GetMyAddress(void)
[取得] 自IPアドレス取得.
Definition: TnbSocket.h:520
virtual void SetSocketListener(IListener *piSocketListener)
[設定] リスナー登録
Definition: TnbSocket.h:466
CAbstractSocket(void)
コンストラクタ
Definition: TnbSocket.h:449
通信受信イベント管理クラス
Definition: TnbReport.h:70
Socket共通アドレス管理クラス
Definition: TnbSocket.h:63
void Set(WORD portNo, DWORD ipAddress=0)
[設定] アドレス設定.
Definition: TnbSocket.h:94
CSocketAddress(WORD portNo=0, DWORD ipAddress=0)
コンストラクタ
Definition: TnbSocket.h:71
void Set(WORD portNo, LPCTSTR lpszIpAddressName)
[設定] アドレス設定.
Definition: TnbSocket.h:109
static DWORD ntohl(DWORD netlong)
[変換] バイトオーダー変換(network to host) unsigned long (32bit) を Network Byte Order から Host Byte Order に変換します。
Definition: TnbSocket.h:279
CStr GetHostName(void) const
[取得] ホスト名取得.
Definition: TnbSocket.h:180
static DWORD ntohs(DWORD netshort)
[変換] バイトオーダー変換(network to host) unsigned short (16bit) を Network Byte Order から Host Byte Order に変換します...
Definition: TnbSocket.h:291
WORD GetPortNo(void) const
[取得] ポートNo取得.
Definition: TnbSocket.h:233
static DWORD htonl(DWORD hostlong)
[変換] バイトオーダー変換(host to network) unsigned long (32bit) を Host Byte Order から Network Byte Order に変換します。
Definition: TnbSocket.h:255
CStr GetAddressString(bool withDns=true) const
[取得] IP アドレス文字列取得.
Definition: TnbSocket.h:198
DWORD GetAddress(void) const
[取得] IP アドレス取得.
Definition: TnbSocket.h:222
bool IsBroadcast(void) const
[確認] ブロードキャスト?.
Definition: TnbSocket.h:243
CSocketAddress(WORD portNo, LPCTSTR lpszIpAddressName)
コンストラクタ.
Definition: TnbSocket.h:82
void Get(SOCKADDR_IN &_sockaddr) const
[取得] IP アドレス&ポート No 取得.
Definition: TnbSocket.h:167
void Get(IN_ADDR &_inaddr) const
[取得] IPアドレス取得.
Definition: TnbSocket.h:135
static WORD htons(WORD hostshort)
[変換] バイトオーダー変換(host to network) unsigned short (16bit) を Host Byte Order から Network Byte Order に変換します...
Definition: TnbSocket.h:267
void Set(const SOCKADDR_IN &sockaddr)
[設定] アドレス設定.
Definition: TnbSocket.h:123
Socketクライアントクラス
Definition: TnbSocket.h:841
CThreadStatus & ReferThreadStatus(void)
[設定] 受信スレッド状態種取得.
Definition: TnbSocket.h:1022
CSocketClient(bool isAutoReconnect=true)
コンストラクタ
Definition: TnbSocket.h:851
virtual void Stop(void)
[実行] 切断
Definition: TnbSocket.h:1001
virtual bool Send(size_t dataSize, LPCVOID lpcvData)
[実行] 送信
Definition: TnbSocket.h:991
virtual CStr GetReportName(void) const
[取得] コミュニケーション名.
Definition: TnbSocket.h:880
SOCKET GetSocket(void) const
[取得] ソケット取得
Definition: TnbSocket.h:901
virtual ~CSocketClient(void)
デストラクタ
Definition: TnbSocket.h:858
virtual DWORD GetReportID(void) const
[取得] コミュニケーションID.
Definition: TnbSocket.h:891
void SetDelayMode(bool boIsDelay)
[設定] 送信遅延モード設定
Definition: TnbSocket.h:870
void Disconnect(void)
[実行] 切断
Definition: TnbSocket.h:1013
virtual bool IsConnect(void) const
[確認] 接続確認
Definition: TnbSocket.h:979
virtual bool IsAlive(void) const
[確認] Aliveチェック.
Definition: TnbSocket.h:969
bool Connect(const CSocketAddress &address)
[実行] 開始
Definition: TnbSocket.h:957
void SetServer(const CSocketAddress &address)
[設定] サーバ設定
Definition: TnbSocket.h:910
virtual bool Start(void)
[実行] 開始
Definition: TnbSocket.h:924
Socket共通受信イベント管理クラス
Definition: TnbSocket.h:322
SOCKET GetSocket(void) const
[取得] ソケット取得
Definition: TnbSocket.h:381
bool GetSockName(CSocketAddress &_address) const
[取得] 受信側情報取得
Definition: TnbSocket.h:793
bool GetPeerName(CSocketAddress &_address) const
[取得] 送信元情報取得
Definition: TnbSocket.h:787
CSocketEvent(CAbstractSocket *pcSocket, SOCKET so, EReportEvent eEvent=ReportEvent_Non, DWORD dwError=0)
コンストラクタ
Definition: TnbSocket.h:772
virtual bool Send(size_t dataSize, LPCVOID lpcvData) const
[送信] データ送信
Definition: TnbSocket.h:780
virtual DWORD GetInterfaceId(void) const
[取得] インターフェースID取得
Definition: TnbSocket.h:355
Socketサーバクラス
Definition: TnbSocket.h:1259
CThreadStatus & ReferThreadStatus(void)
[参照] 受信スレッド状態参照.
Definition: TnbSocket.h:1525
void SetConnectMax(size_t max)
[設定] 接続可能数.
Definition: TnbSocket.h:1315
INT_PTR GetConnectedSockets(CSocketVector *P=NULL) const
[取得] 接続ソケット一覧と数を取得
Definition: TnbSocket.h:1388
virtual void Stop(void)
[実行] サーバをクローズ
Definition: TnbSocket.h:1505
virtual bool Send(size_t dataSize, LPCVOID lpcvData)
[実行] 全部に送信.
Definition: TnbSocket.h:1479
virtual CStr GetReportName(void) const
[取得] コミュニケーション名.
Definition: TnbSocket.h:1291
void SetParameter(const CSocketAddress &address)
[設定] サーバ設定
Definition: TnbSocket.h:1327
virtual ~CSocketServer(void)
デストラクタ
Definition: TnbSocket.h:1270
virtual DWORD GetReportID(void) const
[取得] コミュニケーションID.
Definition: TnbSocket.h:1302
void SetDelayMode(bool boIsDelay)
[設定] 送信遅延モード設定
Definition: TnbSocket.h:1281
CSocketServer(void)
コンストラクタ
Definition: TnbSocket.h:1264
void Disconnect(SOCKET so)
[実行] 指定ソケットの切断
Definition: TnbSocket.h:1445
void Disconnect(void)
[実行] 全ソケットの切断.
Definition: TnbSocket.h:1496
bool GetPeerName(CSocketAddress &_address, SOCKET so)
[取得] 指定ソケットの接続情報取得
Definition: TnbSocket.h:1436
void Close(void)
[実行] サーバをクローズ
Definition: TnbSocket.h:1513
bool Open(const CSocketAddress &address)
[実行] オープン.
Definition: TnbSocket.h:1377
virtual bool IsConnect(void) const
[確認] 接続チェック
Definition: TnbSocket.h:1466
bool IsConnect(SOCKET so) const
[確認] 指定ソケットの接続確認
Definition: TnbSocket.h:1404
virtual bool IsAlive(void) const
[確認] Aliveチェック.
Definition: TnbSocket.h:1456
bool Send(SOCKET so, size_t dataSize, LPCVOID lpcvData)
[実行] データ送信
Definition: TnbSocket.h:1422
virtual bool Start(void)
[実行] 開始.
Definition: TnbSocket.h:1342
bool IsEmpty(void) const
[確認] 空チェック
Definition: TnbStr.h:528
void ReleaseBuffer(void)
[操作] 割り当てたバッファを開放.
Definition: TnbStr.h:954
static CStrT Fmt(const TCHAR *lpszFormat,...)
[作成] 書式付き文字列作成
Definition: TnbStr.h:1206
void Empty(void)
[削除] 空化
Definition: TnbStr.h:197
TYP * GetBuffer(size_t iLength=0)
[操作] 書き込みバッファ要求.
Definition: TnbStr.h:914
Section排他管理クラス
Definition: TnbSync.h:125
スレッド状態管理クラス
Definition: TnbThread.h:128
bool IsAlive(void) const
[確認] スレッドが生きているか
Definition: TnbThread.h:177
スレッド管理クラス
Definition: TnbThread.h:316
bool SetRunner(IRunner *pRunner)
[設定] ランナー、設定
Definition: TnbThread.h:420
bool Stop(DWORD dwWait=15000)
[設定] スレッド停止 スレッドに対して停止要求します。
Definition: TnbThread.h:505
bool Start(LPCTSTR lpszName=NULL)
[設定] スレッド開始
Definition: TnbThread.h:618
経過時間管理クラス
Definition: TnbTickCount.h:57
bool IsPassedAndReset(DWORD dwTime, bool isNow=true)
[確認] 経過確認&リセット.
Definition: TnbTickCount.h:128
void Reset(void)
[設定] リセット.
Definition: TnbTickCount.h:82
virtual size_t GetSize(void) const
[取得] サイズ取得
Definition: TnbVector.h:368
virtual bool Remove(INDEX index)
[削除] 要素一つ削除.
Definition: TnbVector.h:397
virtual bool RemoveAll(void)
[削除] 空化
Definition: TnbVector.h:565
virtual INDEX Add(const TYP &t)
[追加] 要素一つ追加.
Definition: TnbVector.h:383
TNB::CStrT< TCHAR > CStr
文字列クラス
Definition: TnbStr.h:1785
int ToInt(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:367
#define EXCLUSIVE(CLS)
簡易排他制御マクロ.
Definition: TnbSync.h:788
WORD SwapEndian(WORD val)
[変換] エンディアン変換.
Definition: TnbDef.h:1018
TNB Library
Definition: TnbDoxyTitle.txt:2
TNB::CVectorT< SOCKET > CSocketVector
SOCKETの配列型宣言
Definition: TnbSocket.h:35
EReportEvent
通信受信イベント種.
Definition: TnbReport.h:28
@ ReportEvent_End
終了.
Definition: TnbReport.h:31
@ ReportEvent_Error
エラー.
Definition: TnbReport.h:32
@ ReportEvent_Non
イベントなし.
Definition: TnbReport.h:29
@ ReportEvent_Connect
接続.
Definition: TnbReport.h:33
@ ReportEvent_Disconnect
切断.
Definition: TnbReport.h:34
@ ReportEvent_Idle
アイドル.
Definition: TnbReport.h:30
Socket共通のリスナーインターフェース
Definition: TnbSocket.h:424
virtual ~IListener(void)
デストラクタ
Definition: TnbSocket.h:426
virtual bool OnSocketEvent(const CSocketEvent &ev)=0
[通知] イベント発生.
スレッド実行管理ランナーインターフェース
Definition: TnbThread.h:341
bool IsRunnable(void) const
[確認] 実行可能か否か
Definition: TnbThread.h:355
INDEX AddEx(const TYP &t)
[追加] 要素一つ追加.
通信アクセスインターフェース
Definition: TnbReport.h:227
virtual bool Send(size_t dataSize, LPCVOID lpcData)=0
[送信] データ送信