UDPの利用例でエラーがでるのですが

解決


S23  2018-08-26 18:05:43  No: 49452

初めまして、お世話になります。

下記のHPからダウンロードした実行ファイルは正常に動作するのですが、ソースをコンパイルするとエラーが出ます。
https://codezine.jp/article/detail/197

私の開発環境は、windows10 pro 64bitです。
Delphi 10.2を使っていますので、IndyはIndy10だと思います。

エラーはソース中の「←」で示す箇所で下記のエラーが出ます。
[dcc32 エラー] Unit1.pas(36): E2010 'TIdUDPListenerThread' と 'TObject' には互換性がありません

これを解決する方法を教えていただけないでしょうか。

UDPの利用例

procedure TForm1.FormCreate(Sender: TObject);
begin
  // コンポーネントの設定
  Memo1.Text := '';
  IdUDPServer1.DefaultPort := 12345; // 適当なポートを使用
  IdUDPServer1.OnUDPRead   := IdUDPServer1UDPRead; // 受信時のイベント  ←ここでエラーが発生
  // UDPサーバーを起動する
  IdUDPServer1.Active := True;
end;

// ボタンを押したら自分に対し'test'を送信する
procedure TForm1.Button1Click(Sender: TObject);
begin
  IdUDPServer1.Send('127.0.0.1', 12345, 'test'); // 自分自身に送信
end;

// データを受信した時
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  s: string;
begin
  // TStreamを文字列に変換する
  SetLength(s, AData.Size);
  AData.Read(s[1], AData.Size);
  // メモの先頭に受信した文字列を挿入
  Memo1.Lines.Insert(0, s);
end;


igy  2018-08-26 18:28:49  No: 49453

Indyは、ほとんど使ったことがないので、詳しくないのですが、

Delphi10.2のTIdUDPServerのOnUDPReadイベントは、

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
begin

end;

みたいなので、

> // データを受信した時 
> procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream; 
>   ABinding: TIdSocketHandle); 

の引数を、同じように合わせるのがよさそうですね。


AAA  2018-08-26 18:34:19  No: 49454

>Delphi 7に付属しているIndy 9のコンポーネントを利用して、手軽に作ってみます。

Indy9 用だよねソース
ソース会員じゃないとダウンロードできないし

[dcc32 エラー] Unit1.pas(36): E2010 'TIdUDPListenerThread' と 'TObject' には互換性がありません 
の原因は
Indy9 と Indy10 の IdUPDServer の OnUPDRead のイベントの型が違うから

//Indy9
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream; 
   ABinding: TIdSocketHandle); 

//Indy10
procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);

1個目のパラメータが Sender: TObject; と  AThread: TIdUDPListenerThread;
と型に互換性がないと

イベントを付けなおせばいけるけど今度は

AData の型が違うからそこ直さないと駄目

AData: TStream;  //Indy9
AData: TIdBytes; //Indy10


s23  2018-08-26 19:21:11  No: 49455

早速のご返答ありがとうございます。

教えていただいたように書き直してみたのですが、TIdBytesが未定義の識別子になってしまいます。

> procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; 
>    const AData: TIdBytes; ABinding: TIdSocketHandle); 
                  ^^^^^^^^
これを解決するにはどうすれば良いのでしょうか

因みに、元のソースファイルは下記のとおりです。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer,
  IdSocketHandle;

type
  TForm1 = class(TForm)
    IdUDPServer1: TIdUDPServer;
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
      ABinding: TIdSocketHandle);
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// コンポーネントの設定
procedure TForm1.FormCreate(Sender: TObject);
begin
  IdUDPServer1.DefaultPort := 12345;
  IdUDPServer1.OnUDPRead := IdUDPServer1UDPRead;
  IdUDPServer1.Active := True;
  Memo1.Text := '';
end;

// ボタンを押したら全員に対し'test'を送信する
procedure TForm1.Button1Click(Sender: TObject);
begin
  IdUDPServer1.Broadcast('test',12345);
end;

// データを受信した時
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  s: string;
begin
  SetLength(s, AData.Size);
  AData.Read(s[1], AData.Size);
  Memo1.Lines.Insert(0, s);
end;

end.


igy  2018-08-26 19:34:38  No: 49456

uses に、IdGlobal を追加してみるのは、いかがですか?


s23  2018-08-26 19:55:34  No: 49457

おかげさまで、TIdBytesのエラーは直りましたが
AData.SizeとAData.Readが「TIdBytesはSizeとReadという名前のメンバを含んでいません」となります。
これはどうしたらよろしいのでしょうか。

// データを受信した時
procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
   const AData: TIdBytes; ABinding: TIdSocketHandle);
var
  s: string;
begin
  SetLength(s, AData.Size);
  AData.Read(s[1], AData.Size);
  Memo1.Lines.Insert(0, s);
end;


igy  2018-08-26 20:08:52  No: 49458

ソースコードみたら、
TIdBytes = array of Byte;
みたいです。


s23  2018-08-26 20:25:54  No: 49459

私はランクを中級者としましたが、s23年生まれで、昔はTurboPascalをかなり使っていましたが、Delphiになってからは基本が理解出来ていないため、いまいち分からないことが多すぎて困っております。
特に、ソケット通信は初めてのチャレンジです。

できましたら、具体的にどこをどう直せば良いのか、ご教授いただけないでしょうか。

申し訳ありませんが、よろしくお願いいたします。


Mr.XRAY  2018-08-27 02:57:03  No: 49460

>具体的にどこをどう直せば良いのか、ご教授いただけないでしょうか。

ご教授などとたいそうなことはできません.

TIdBytes = array of Byte; 

というのはバイト配列のことです.
ですので,バイト配列を文字列にします.

Broadcast では ASCII 文字しか送信できないようなので string 型ではなく AnsiString 型を使用します.
AnsiString の ASCII 文字は 1 バイトが 1 文字です.

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var
  s: AnsiString;
begin
  SetLength(s, Length(AData));
  Move(AData[0], s[1], Length(AData));
  Memo1.Lines.Insert(0, string(s));
end;

>申し訳ありませんが、よろしくお願いいたします。 

提示されたキーワードを頼りに Google 等で検索するとよろしいかと.
それと,ネット上のこういう掲示板では,年齢,男女,経歴,地位はあまり関係ないと思います.
年をとっていることは免罪符にはなりません.多分


Mr.XRAY  2018-08-27 05:50:21  No: 49461

Move 関数を使用するというは思いつかないことがあります.
そんな時は以下のように 1 バイトづつ処理することも可能です.
AnsiString, AnsiChar を使用するのがミソというかポイントですね.

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var
  LIndex : Integer;
  LText  : AnsiString;
begin
  LText := '';
  for LIndex := 0 to Length(AData) - 1 do begin
    LText := LText + AnsiChar(AData[LIndex]);
  end;
  Memo1.Lines.Insert(0, string(LText));
end;


Mr.XRAY  2018-08-27 08:09:29  No: 49462

ゴメンなさい.TEncoding を使えば簡単でした.

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var
  LString : string;
begin
  LString := TEncoding.ASCII.GetString(AData);
  Memo1.Lines.Insert(0, LString);
end;


s23  2018-08-27 18:11:59  No: 49463

igyさん、AAAさん、Mr.XRAYさん、ご回答ありがとうございました。

おかげさまで、解決することができました。
これからも新しいことにチャレンジして行けそうです。

> 年をとっていることは免罪符にはなりません.多分

つい甘えてしまい、申し訳ありませんでした。
これからも、生涯現役のつもりで頑張ります。


Mr.XRAY  2018-08-28 04:01:08  No: 49464

ものはついでと言います
このスレッドを読んでいて,実際にサンプルょをやってみて,日本語は ?
と思った方,以下にサンプルがあります.
( 検索すれば見つかるわけですが...)

[ TIdUDPServerで日本語文字列を送受信するには ? 山本隆の開発日誌 ]
https://www.gesource.jp/weblog/?p=6036

Delphi のコードにすると,例えば以下のようになると思います.

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var
  LString : string;
begin
  LString := TEncoding.Unicode.GetString(AData);
  Memo1.Lines.Insert(0, LString);
end;

// ボタンを押したら文字列を送信する
procedure TForm1.Button1Click(Sender: TObject);
begin
  //文字列をUTF16LEで送信する
  //自分自身に送信
  IdUDPServer1.Send('127.0.0.1', 12345, '日本語 ABC 文字列', IndyTextEncoding_UTF16LE);
end;


Mr.XRAY  2018-08-28 04:07:42  No: 49465

実行時に現れるダイアログについては以下を参考にしてください.
例によって「難解」な記事ですのであしからず.

[ Windows セキュリティの重要な警告 ] ダイアログ ]
http://mrxray.on.coocan.jp/Delphi/Others/MicrosoftSecurity.htm


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加