TNB Library
TnbSocketUdp.h
[詳解]
1#pragma once
18#include "TnbSocket.h"
19
20
21
22//TNB Library
23namespace TNB
24{
25
26
27
63{
64 DEFSUPER(CAbstractSocket);
65public:
66
68 CSocketUdp(void) : _super(), m_isStopping(false), m_soData(INVALID_SOCKET), m_isBroadcast(-1), m_bufferSize(0), m_isAddressBroadcast(false)
69 {
70 m_threadReceiver.SetRunner(this);
71 m_addrFrom.Init();
72 }
73
75 virtual ~CSocketUdp(void)
76 {
77 Stop();
78 }
79
85 virtual CStr GetReportName(void) const
86 {
87 return CStr::Fmt(_T("SocketUDP[%u]:"), m_baseAddress.GetPortNo());
88 }
89
96 virtual DWORD GetReportID(void) const
97 {
98 return TNBVIW_KIND_SOCK_U + m_baseAddress.GetPortNo();
99 }
100
106 SOCKET GetSocket(void) const
107 {
108 return m_soData;
109 }
110
117 WORD GetMaxDatagram(void)
118 {
119 WORD w = m_GetMaxUdpDg(m_soData);
120 if ( w == 0 )
121 {
122 w = 1500;
123 }
124 return w;
125 }
126
135 void SetBaseAddress(const CSocketAddress& address)
136 {
137 StartUp();
138 Stop();
139 m_baseAddress = address;
140 }
141
147 {
148 return m_baseAddress;
149 }
150
157 virtual bool Start(void)
158 {
159 StartUp();
160 Stop();
161 // 自分用ソケット構造体の初期化
162 TSockAddr addr;
163 addr.Init();
164 addr.sin_family = AF_INET; // TCP/IPを指定
165 m_baseAddress.Get(addr);
166 // UDP オープン
167 SOCKET so = ::socket(AF_INET, SOCK_DGRAM, 0);
168 if ( so == SOCKET_ERROR )
169 {
170 TRACE1( "::socket() error = %d\n", ::WSAGetLastError() );
171 return false;
172 }
173 if ( ::bind(so, addr, addr.GetSize()) == SOCKET_ERROR )
174 {
175 TRACE1( "::bind() error = %d\n", ::WSAGetLastError() );
176 ::closesocket(so);
177 return false;
178 }
179 m_soData = so;
180 m_isBroadcast = -1;
181 // 受信スレッド開始
182 if ( m_baseAddress.GetPortNo() != 0 )
183 {
184 m_bufferSize = GetMaxDatagram();
185 ASSERTLIB(m_bufferSize > 0);
186 delete m_lpcBuffer;
187 m_lpcBuffer = new char[m_bufferSize];
188 ASSERTLIB(m_lpcBuffer != NULL);
189 #ifdef _DEBUG
190 m_threadReceiver.Start(CStr::Fmt(_T("SocketUDP[%u]監視"), m_baseAddress.GetPortNo()));
191 #else
192 m_threadReceiver.Start();
193 #endif
194 }
195 return true;
196 }
197
204 virtual bool IsAlive(void) const
205 {
206 return m_soData != INVALID_SOCKET;
207 }
208
215 virtual bool IsConnect(void) const
216 {
217 return m_soData != INVALID_SOCKET;
218 }
219
225 const CSocketAddress& GetAddressee(void) const
226 {
227 return m_addressee;
228 }
229
237 bool SetAddressee(const CSocketAddress& address)
238 {
239 m_addressee = address;
240 m_isAddressBroadcast = false;
241 return m_SetAddress(address);
242 }
243
250 void SetBroadcastPort(WORD portNo, DWORD address = INADDR_BROADCAST)
251 {
252 CSocketAddress a(portNo, address);
253 m_addressee = a;
254 m_isAddressBroadcast = true;
255 m_SetAddress(a);
256 }
257
266 virtual bool Send(size_t dataSize, LPCVOID lpcvData)
267 {
268 _super::m_OnSend(dataSize, lpcvData);
269 return m_Send(m_soData, dataSize, lpcvData);
270 }
271
275 virtual void Stop(void)
276 {
277 m_isStopping = true;
278 m_CloseDataSocket();
279 m_threadReceiver.Stop();
280 if ( IsConnect() )
281 {
282 m_CloseDataSocket();
283 }
284 m_isStopping = false;
285 }
286
292 {
293 return m_threadReceiver;
294 }
295
302 {
303 return m_threadReceiver;
304 }
305
311 size_t GetReceivedBufferSize(void) const
312 {
313 int len = 0;
314 int lenlen = sizeof(len);
315 int r = ::getsockopt(m_soData, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char *>(&len), &lenlen);
316 return static_cast<size_t>((r == SOCKET_ERROR) ? 0 : len);
317 }
318
325 bool SetReceivedBufferSize(size_t size)
326 {
327 if ( size < INT_MAX )
328 {
329 int len = ToInt(size);
330 int r = ::setsockopt(m_soData, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char *>(&len), sizeof(len));
331 if ( r != SOCKET_ERROR )
332 {
333 return size == GetReceivedBufferSize();
334 }
335 }
336 return false;
337 }
338
345 static bool WakeupOnLan(const BYTE* pbMacAddr)
346 {
347 CSocketUdp udp;
348 udp.Start();
349 udp.SetBroadcastPort(7);
350 ASSERTLIB( udp.GetAddressee().GetPortNo() == 7 );
351 const int MACSIZE = 6;
352 const int MACLOOP = 16;
353 char sendbuf[MACLOOP * MACSIZE + MACSIZE];
354 // 送信データ作成
355 ::FillMemory(&sendbuf[0], MACSIZE, 0xFF);
356 loop ( i, MACLOOP )
357 {
358 ::CopyMemory(&sendbuf[MACSIZE + i * MACSIZE], pbMacAddr, MACSIZE);
359 }
360 return udp.Send(MACLOOP * MACSIZE + MACSIZE, sendbuf);
361 }
362
363protected:
364
365 #ifndef _TnbDOXYGEN //Document作成用シンボル
374 virtual bool m_GetPeerName(CSocketAddress& _address, SOCKET so)
375 {
376 _address.Set(m_addrFrom);
377 return true;
378 }
387 virtual bool m_Send(SOCKET so, size_t dataSize, LPCVOID lpcvData)
388 {
389 BOOL isAddressBroadcast = m_isAddressBroadcast;
390 if ( m_isBroadcast != (!! isAddressBroadcast) )
391 {
392 ::setsockopt(so, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char *>(&isAddressBroadcast), sizeof(isAddressBroadcast));
393 m_isBroadcast = !! isAddressBroadcast;
394 }
395 int iRc = ::sendto(so, static_cast<const char*>(lpcvData), ToInt(dataSize), 0, m_sockaddrPartner, TSockAddr::GetSize());
396 TRACE3( "::sendto(%u) result = %d error = %d\n", dataSize, iRc, ::WSAGetLastError() );
397 return iRc == ToInt(dataSize);
398 }
399 #endif // _TnbDOXYGEN
400
401private:
403 void m_CloseDataSocket(void)
404 {
405 if ( m_soData != INVALID_SOCKET )
406 {
407 SOCKET so = m_soData;
408 m_soData = INVALID_SOCKET;
409 TRACE1( "SocketUDP[%u]:Closed\n", m_baseAddress.GetPortNo() );
410 ::closesocket(so);
411 }
412 }
417 virtual DWORD Run(void)
418 {
419 if ( m_OnSocketEvent(CSocketEvent(this, m_soData, ReportEvent_Connect)) )
420 {
421 CTickCount tickIdle;
422 while ( IsRunnable() )
423 {
424 int iInterval = _super::GetIdleInterval();
425 if ( iInterval > 0 )
426 {
427 fd_set tFdSet;
428 FD_ZERO(&tFdSet);
429 FD_SET(m_soData, &tFdSet);
430 int iSelTime = iInterval;
431 timeval tTimeVal = { iSelTime / 1000, iSelTime % 1000 };
432 ::select(ToInt(m_soData + 1), &tFdSet, NULL, NULL, &tTimeVal);
433 if ( ! FD_ISSET(m_soData, &tFdSet) )
434 {
435 //== データなし
436 if ( iInterval > 0 && tickIdle.IsPassedAndReset(iInterval) )
437 {
438 if ( ! m_OnSocketEvent(CSocketEvent(this, m_soData, ReportEvent_Idle)) )
439 {
440 break; //切断
441 }
442 }
443 continue;
444 }
445 }
446 TTRACE1( "SocketUDP[%u]:受信\n", m_baseAddress.GetPortNo() );
447 int iFromLen = m_addrFrom.GetSize();
448 int iLen = ::recvfrom(m_soData, m_lpcBuffer, ToInt(m_bufferSize), 0, m_addrFrom, &iFromLen);
449 if ( iLen == SOCKET_ERROR )
450 {
451 if ( ! m_isStopping )
452 {
453 int iError = ::WSAGetLastError();
454 TRACE2( "::recv(%d) error = %d\n", m_soData, iError );
455 if ( ! m_OnSocketEvent(CSocketEvent(this, m_soData, ReportEvent_Error, iError)) )
456 {
457 break;
458 }
459 }
460 else
461 {
462 break;
463 }
464 }
465 else if ( iLen != 0 )
466 {
467 CSocketEvent s(this, m_soData);
468 s.SetData(iLen, m_lpcBuffer);
469 if ( ! m_OnSocketEvent(s) )
470 {
471 break;
472 }
473 }
474 else
475 {
476 //データ無し
477 }
478 tickIdle.Reset();
479 }
480 m_OnSocketEvent(CSocketEvent(this, m_soData, ReportEvent_Disconnect));
481 }
482 m_OnSocketEvent(CSocketEvent(this, m_soData, ReportEvent_End));
483 return 0;
484 }
485 CThread m_threadReceiver;
486 SOCKET m_soData;
487 CSocketAddress m_baseAddress;
488 CSocketAddress m_addressee;
489 bool m_isAddressBroadcast;
490 TSockAddr m_addrFrom;
491 BOOL m_isBroadcast;
492 size_t m_bufferSize;
493 bool m_isStopping;
494};
495
496
497
515{
516 DEFSUPER(CSocketUdp);
517public:
518
519 #pragma pack(push)
520 #pragma pack(1)
532 {
533 DWORD ipAddress;
534 WORD portNo;
540 TDataHeader(WORD pn = 0, DWORD ip = 0) : ipAddress(ip), portNo(pn)
541 {
542 }
548 {
549 operator=(addr);
550 }
555 operator CSocketAddress() const
556 {
558 }
563 void operator=(const CSocketAddress& addr)
564 {
565 ipAddress = addr.GetAddress();
566 portNo = addr.GetPortNo();
567 }
568 };
569 #pragma pack(pop)
570
571
572 //---
573
574
577 {
578 }
579
590 bool Broadcast(size_t dataSize, LPCVOID lpcvData)
591 {
592 _super::m_OnSend(dataSize, lpcvData);
593 C_ASSERT( sizeof(TDataHeader) == 6 );
594 if ( dataSize < sizeof(TDataHeader) )
595 {
596 return false;
597 }
598 const TDataHeader* p = static_cast<const TDataHeader*>(lpcvData);
600 if ( p->ipAddress == 0 )
601 {
602 _super::SetBroadcastPort(h.portNo);
603 }
604 else
605 {
606 _super::SetBroadcastPort(h.portNo, p->ipAddress);
607 }
608 const BYTE* b = static_cast<const BYTE*>(lpcvData);
609 return m_Send(_super::GetSocket(), dataSize - sizeof(TDataHeader), &b[sizeof(TDataHeader)]);
610 }
611
621 virtual bool Send(size_t dataSize, LPCVOID lpcvData)
622 {
623 _super::m_OnSend(dataSize, lpcvData);
624 C_ASSERT( sizeof(TDataHeader) == 6 );
625 if ( dataSize < sizeof(TDataHeader) )
626 {
627 return false;
628 }
629 const TDataHeader* p = static_cast<const TDataHeader*>(lpcvData);
632 //
633 EXCLUSIVE( &m_syncSend );
634 _super::SetAddressee(sa);
635 const BYTE* b = static_cast<const BYTE*>(lpcvData);
636 return m_Send(_super::GetSocket(), dataSize - sizeof(TDataHeader), &b[sizeof(TDataHeader)]);
637 }
638
646 {
647 TDataHeader dh = h;
648 if ( dh.ipAddress == 0 )
649 {
650 dh.ipAddress = _super::GetAddressee().GetAddress();;
651 }
652 if ( dh.portNo == 0 )
653 {
654 dh.portNo = _super::GetAddressee().GetPortNo();
655 }
656 return dh;
657 }
658
659protected:
660
661 #ifndef _TnbDOXYGEN //Document作成用シンボル
668 virtual bool m_OnSocketEvent(CSocketEvent& e)
669 {
670 CWorkMem w;
671 CSocketEvent se = e;
672 if ( se.HasData() )
673 {
674 w.Resize(sizeof(TDataHeader) + se.GetDataSize());
675 BYTE* b = w.Ref();
676 TDataHeader* h = reinterpret_cast<TDataHeader*>(b);
678 e.GetPeerName(sa);
679 h->ipAddress = sa.GetAddress();
680 h->portNo = sa.GetPortNo();
681 memcpy(&b[sizeof(TDataHeader)], e.GetData(), e.GetDataSize());
682 se.SetData(w.GetSize(), w);
683 }
684 return _super::m_OnSocketEvent(se);
685 }
686 #endif // _TnbDOXYGEN
687
688private:
689 CSyncSection m_syncSend;
690// DWORD m_defaultAddr; ///< デフォルトアドレス
691// WORD m_defaultPort; ///< デフォルトポート
692};
693
694
695
696};
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
ソケットのアクセス関係のヘッダ
Socket共通クラス
Definition: TnbSocket.h:406
static void StartUp(void)
[設定] SOCKET初期化.
Definition: TnbSocket.h:478
friend class CSocketEvent
フレンドクラス定義
Definition: TnbSocket.h:408
size_t GetDataSize(void) const
[取得] データ長取得
Definition: TnbReport.h:139
void SetData(size_t dataSize, LPCVOID lpcData)
[設定] データ設定.
Definition: TnbReport.h:200
bool HasData(void) const
[確認] Dataを持っているか
Definition: TnbReport.h:120
Socket共通アドレス管理クラス
Definition: TnbSocket.h:63
WORD GetPortNo(void) const
[取得] ポートNo取得.
Definition: TnbSocket.h:233
DWORD GetAddress(void) const
[取得] IP アドレス取得.
Definition: TnbSocket.h:222
void Get(IN_ADDR &_inaddr) const
[取得] IPアドレス取得.
Definition: TnbSocket.h:135
Socket共通受信イベント管理クラス
Definition: TnbSocket.h:322
拡張 Socket UPD 通信
Definition: TnbSocketUdp.h:515
bool Broadcast(size_t dataSize, LPCVOID lpcvData)
[設定] ブロードバンド送信指定
Definition: TnbSocketUdp.h:590
virtual bool Send(size_t dataSize, LPCVOID lpcvData)
[実行] 送信
Definition: TnbSocketUdp.h:621
TDataHeader AdjustDataHeader(const TDataHeader &h) const
[取得] データヘッダ調整.
Definition: TnbSocketUdp.h:645
CSocketUdpEx(void)
コンストラクタ
Definition: TnbSocketUdp.h:576
SocketUPDクラス
Definition: TnbSocketUdp.h:63
CThreadStatus & ReferThreadStatus(void)
[参照] 受信スレッド状態参照.
Definition: TnbSocketUdp.h:291
virtual void Stop(void)
[実行] 切断
Definition: TnbSocketUdp.h:275
const CSocketAddress & GetAddressee(void) const
[取得] 送信先アドレス取得.
Definition: TnbSocketUdp.h:225
virtual bool Send(size_t dataSize, LPCVOID lpcvData)
[実行] 送信
Definition: TnbSocketUdp.h:266
virtual CStr GetReportName(void) const
[取得] コミュニケーション名.
Definition: TnbSocketUdp.h:85
SOCKET GetSocket(void) const
[取得] ソケット取得
Definition: TnbSocketUdp.h:106
virtual DWORD GetReportID(void) const
[取得] コミュニケーションID.
Definition: TnbSocketUdp.h:96
virtual ~CSocketUdp(void)
デストラクタ
Definition: TnbSocketUdp.h:75
bool SetReceivedBufferSize(size_t size)
[設定] 受信バッファサイズ設定.
Definition: TnbSocketUdp.h:325
CSocketUdp(void)
コンストラクタ
Definition: TnbSocketUdp.h:68
void SetBroadcastPort(WORD portNo, DWORD address=INADDR_BROADCAST)
[設定] ブロードバンド送信指定
Definition: TnbSocketUdp.h:250
bool SetAddressee(const CSocketAddress &address)
[設定] 送信先アドレス指定
Definition: TnbSocketUdp.h:237
static bool WakeupOnLan(const BYTE *pbMacAddr)
[送信] Wake up on LAN
Definition: TnbSocketUdp.h:345
void SetBaseAddress(const CSocketAddress &address)
[設定] ベースアドレス設定.
Definition: TnbSocketUdp.h:135
WORD GetMaxDatagram(void)
[取得] UDP送信最大サイズ取得.
Definition: TnbSocketUdp.h:117
CThreadStatus & GetReceiveThreadStatus(void)
[参照] 受信スレッド状態参照.
Definition: TnbSocketUdp.h:301
const CSocketAddress & GetBaseAddress(void) const
[取得] ベースアドレス取得.
Definition: TnbSocketUdp.h:146
virtual bool IsConnect(void) const
[確認] 接続チェック.
Definition: TnbSocketUdp.h:215
virtual bool IsAlive(void) const
[確認] Aliveチェック.
Definition: TnbSocketUdp.h:204
virtual bool Start(void)
[実行] 開始
Definition: TnbSocketUdp.h:157
size_t GetReceivedBufferSize(void) const
[取得] 受信バッファサイズ取得.
Definition: TnbSocketUdp.h:311
static CStrT Fmt(const TCHAR *lpszFormat,...)
[作成] 書式付き文字列作成
Definition: TnbStr.h:1206
Section排他管理クラス
Definition: TnbSync.h:125
スレッド状態管理クラス
Definition: TnbThread.h:128
スレッド管理クラス
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
size_t GetSize(void) const
[取得] サイズ取得
Definition: TnbDef.h:665
void Resize(size_t l)
[設定] サイズ再設定
Definition: TnbDef.h:672
const TYP * Ref(void) const
[取得] ポインタ取得
Definition: TnbDef.h:712
int ToInt(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:367
#define EXCLUSIVE(CLS)
簡易排他制御マクロ.
Definition: TnbSync.h:788
TNB Library
Definition: TnbDoxyTitle.txt:2
@ ReportEvent_End
終了.
Definition: TnbReport.h:31
@ ReportEvent_Error
エラー.
Definition: TnbReport.h:32
@ ReportEvent_Connect
接続.
Definition: TnbReport.h:33
@ ReportEvent_Disconnect
切断.
Definition: TnbReport.h:34
@ ReportEvent_Idle
アイドル.
Definition: TnbReport.h:30
拡張 Socket UDP 通信データヘッダ.
Definition: TnbSocketUdp.h:532
void operator=(const CSocketAddress &addr)
[代入] 代入オペレータ.
Definition: TnbSocketUdp.h:563
TDataHeader(const CSocketAddress &addr)
代入コンストラクタ.
Definition: TnbSocketUdp.h:547
DWORD ipAddress
IPアドレス
Definition: TnbSocketUdp.h:533
TDataHeader(WORD pn=0, DWORD ip=0)
コンストラクタ.
Definition: TnbSocketUdp.h:540
スレッド実行管理ランナーインターフェース
Definition: TnbThread.h:341
bool IsRunnable(void) const
[確認] 実行可能か否か
Definition: TnbThread.h:355