0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++ Builder XE4, 10.2 Tokyo > UDP > 遠隔地PCから問い合わせがあった時にフォーム上のTLabel Captionを返信する v0.1,v0.2

Last updated at Posted at 2017-02-21
動作環境
C++ Builder XE4

RAD Studio 10.2 Tokyo Update 2 (追記: 2017/12/28)
   v0.1を動作確認した

実装内容

  • UDPでTLabelのコンポーネント名を受信する
  • 取得したコンポーネント名を元にTLabelコンポーネントを探す
  • 見つかったコンポーネントのCaption情報を返信する

v0.1

実装

Unit1.h
//---------------------------------------------------------------------------

# ifndef Unit1H
# define Unit1H
//---------------------------------------------------------------------------
# include <System.Classes.hpp>
# include <Vcl.Controls.hpp>
# include <Vcl.StdCtrls.hpp>
# include <Vcl.Forms.hpp>
# include <IdBaseComponent.hpp>
# include <IdComponent.hpp>
# include <IdSocketHandle.hpp>
# include <IdUDPBase.hpp>
# include <IdUDPServer.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TLabel *Label1;
	TIdUDPServer *IdUDPServer1;
	TMemo *Memo1;
	TLabel *L_myIP;
	void __fastcall IdUDPServer1UDPRead(TIdUDPListenerThread *AThread, const TIdBytes AData,
          TIdSocketHandle *ABinding);
	void __fastcall FormShow(TObject *Sender);
private:	// ユーザー宣言
	String __fastcall getLabelCaption(String componentName);
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
# endif
Unit1.cpp
//---------------------------------------------------------------------------

# include <vcl.h>
# pragma hdrstop

# include "Unit1.h"
//---------------------------------------------------------------------------
# pragma package(smart_init)
# pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	IdUDPServer1->DefaultPort = 7000;
	IdUDPServer1->Active = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdUDPServer1UDPRead(TIdUDPListenerThread *AThread, const TIdBytes AData,
		  TIdSocketHandle *ABinding)
{
	// 1. Receive command (Component name)
	String rcvdStr;
	Idglobal::_di_IIdTextEncoding encSJIS;
	encSJIS = IndyTextEncoding(932);
	int init_pos = 0;
	rcvdStr = encSJIS->GetString(AData, init_pos, AData.Length);

	// for debug
	Memo1->Lines->Add(L"rcvd:" + rcvdStr);

	// 2. return Caption of the component
	String peerIP = ABinding->PeerIP;
	int peerPort = ABinding->PeerPort;
	String retStr = getLabelCaption(/* componentName=*/rcvdStr);
	IdUDPServer1->Send(peerIP, peerPort, retStr, encSJIS);
}
//---------------------------------------------------------------------------

String __fastcall TForm1::getLabelCaption(String componentName)
{
	TLabel *lblPtr = (TLabel *)FindComponent(componentName);
	if (lblPtr == NULL) {
		return L"";
	}

	return lblPtr->Caption;
}

void __fastcall TForm1::FormShow(TObject *Sender)
{
	Label1->Caption = L"From Label1";

	// show IP address
	TIdStack::IncUsage();
	L_myIP->Caption = GStack->LocalAddress;
	TIdStack::DecUsage();
}
//---------------------------------------------------------------------------

実行例

L_myIPというコマンドの応答

192.168.0.31

Label1というコマンドの応答

From Label1

任意のTLabelコンポーネントに対してCaptionを取得できる。

v0.2 > STX, ETX, BCC追加

変更点

  • 応答文字列にコマンド文字列(と",")を追加
  • <STX>,<ETX>でペイロードを囲み、<ETX>の後に<BCC>を付けるようにした。
    • <BCC>の計算はペイロード+<ETX>をunsigned charで総和とったもの

実装

Unit1.h
//---------------------------------------------------------------------------

# ifndef Unit1H
# define Unit1H
//---------------------------------------------------------------------------
# include <System.Classes.hpp>
# include <Vcl.Controls.hpp>
# include <Vcl.StdCtrls.hpp>
# include <Vcl.Forms.hpp>
# include <IdBaseComponent.hpp>
# include <IdComponent.hpp>
# include <IdSocketHandle.hpp>
# include <IdUDPBase.hpp>
# include <IdUDPServer.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TLabel *Label1;
	TIdUDPServer *IdUDPServer1;
	TMemo *Memo1;
	TLabel *L_myIP;
	void __fastcall IdUDPServer1UDPRead(TIdUDPListenerThread *AThread, const TIdBytes AData,
          TIdSocketHandle *ABinding);
	void __fastcall FormShow(TObject *Sender);
private:	// ユーザー宣言
	String __fastcall getLabelCaption(String componentName);
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
# endif
Unit1.cpp
//---------------------------------------------------------------------------

# include <vcl.h>
# pragma hdrstop

# include "Unit1.h"
//---------------------------------------------------------------------------
# pragma package(smart_init)
# pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------


/*
v0.2 2017/02/21
	- add getWrappedString()
	- add calc_bcc()
v0.1 2017/02/21
	- add IdUDPServer1UDPRead()
	- add getLabelCaption()
	- add FormShow()
*/


__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	IdUDPServer1->DefaultPort = 7000;
	IdUDPServer1->Active = true;
}
//---------------------------------------------------------------------------

static unsigned char calc_bcc(char *srcPtr, int len)
{
	// srcPtr: <STX>ペイロード<ETX>の文字列
	// ペイロードと<ETX>から<BCC>を計算する
	//

	unsigned char bcc = 0;

	for(int idx=0; idx<len; idx++) {
		if (idx==0) {
			continue; // <STX>はスキップする
		}
		bcc += srcPtr[idx];
	}

	return bcc;
}

static AnsiString getWrappedString(AnsiString srcStr)
{
	AnsiString retStr = srcStr;
	char szbuf[50] = {0};
	szbuf[0] = 0x02; // STX
	strncpy(&szbuf[1], srcStr.c_str(), srcStr.Length());
	int last = srcStr.Length();
	szbuf[++last] = 0x03; // ETX

	unsigned char bcc = calc_bcc(szbuf, strlen(szbuf));
	szbuf[++last] = bcc;

	return AnsiString(szbuf);
}

void __fastcall TForm1::IdUDPServer1UDPRead(TIdUDPListenerThread *AThread, const TIdBytes AData,
		  TIdSocketHandle *ABinding)
{
	// 1. Receive command (Component name)
	AnsiString rcvdStr;
	Idglobal::_di_IIdTextEncoding encSJIS;
	encSJIS = IndyTextEncoding(932);
	int init_pos = 0;
	rcvdStr = encSJIS->GetString(AData, init_pos, AData.Length);

	// for debug
	Memo1->Lines->Add(L"rcvd:" + rcvdStr);

	// 2. return Caption of the component
	AnsiString peerIP = ABinding->PeerIP;
	int peerPort = ABinding->PeerPort;
	AnsiString capStr = getLabelCaption(/* componentName=*/rcvdStr);
	AnsiString wrpStr = getWrappedString(rcvdStr + L"," + capStr);
	IdUDPServer1->Send(peerIP, peerPort, wrpStr, encSJIS);
}
//---------------------------------------------------------------------------

String __fastcall TForm1::getLabelCaption(String componentName)
{
	TLabel *lblPtr = (TLabel *)FindComponent(componentName);
	if (lblPtr == NULL) {
		return L"";
	}

	return lblPtr->Caption;
}

void __fastcall TForm1::FormShow(TObject *Sender)
{
	Label1->Caption = L"From Label1";

	// show IP address
	TIdStack::IncUsage();
	L_myIP->Caption = GStack->LocalAddress;
	TIdStack::DecUsage();
}
//---------------------------------------------------------------------------

動作確認

NonSoftさんの「UDP/IPテストツール」を使わせていただきました。
http://nonsoft.la.coocan.jp/Download/UdpTool/index.html

このツールは、ASCII文字列に加えて、<STX>などの文字を"<STX>"として表示してくれます。
このため、上記のような通信の確認がしやすくなります。

結果
送-> 192.168.0.31 (7000 )L_myIP
->受 192.168.0.31 (7000 )<STX>L_myIP,192.168.0.31<ETX><b2>
送-> 192.168.0.31 (7000 )L_myIP
->受 192.168.0.31 (7000 )<STX>L_myIP,192.168.0.31<ETX><b2>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?