Help us understand the problem. What is going on with this article?

C++ Builder XE4 > TCP > Clientからの送信と受信処理 > v0.1:whileでの受信タイムアウト, v0.2:ReadLn()での受信タイムアウト | 余談: 記事消した...

More than 3 years have passed since last update.
動作環境
C++ Builder XE4

処理概要

  • TCPサーバーに接続する
  • TCPサーバーに文字列を送信する
  • TCPサーバーからの応答を受信する
    • タイムアウト付き

code v0.1 (Whileでの受信待ち)

備考: E_ipadrとE_portはPasswordCharを設定している

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 <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
#include <Vcl.ComCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE で管理されるコンポーネント
    TEdit *E_ipadr;
    TButton *Button1;
    TIdTCPClient *IdTCPClient1;
    TLabel *Label1;
    TLabel *Label2;
    TEdit *E_port;
    TLabel *Label3;
    TEdit *E_sendText;
    TStatusBar *StatusBar1;
    void __fastcall Button1Click(TObject *Sender);
private:    // ユーザー宣言
    void __fastcall commTCP(int timeout_msec);
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)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::commTCP(int timeout_msec)
{
    // 1. Connect
    IdTCPClient1->Host = E_ipadr->Text;
    int portNum = StrToIntDef(E_port->Text, -1);
    if (portNum < 0) {
        String wrnmsg = L"Error: Invalid port number:" + E_port->Text;
        MessageDlg(wrnmsg, mtError, TMsgDlgButtons() << mbOK, 0);
        return; // fail to get portNum
    }
    IdTCPClient1->Port = portNum;
    try {
        IdTCPClient1->Connect();
    } catch (...) {
        String wrnmsg = L"Failed to connect to " + E_ipadr->Text;
        MessageDlg(wrnmsg, mtError, TMsgDlgButtons() << mbOK, 0);
        return;
    }

    // 2. send
    String sndTxt = E_sendText->Text;
    IdTCPClient1->IOHandler->WriteLn(sndTxt);

    // 3. receive
    String rcvd;
    DWORD startTim = GetTickCount();
    while(1) {
        if (GetTickCount() - startTim > timeout_msec) {
            String wrnmsg = L"Error: Receive timeout";
            MessageDlg(wrnmsg, mtError, TMsgDlgButtons() << mbOK, 0);
            break;
        }
        if (IdTCPClient1->IOHandler->InputBufferIsEmpty() == false) {
            Application->ProcessMessages();
            Sleep(100);
            continue;
        }
        if (IdTCPClient1->IOHandler->CheckForDataOnSource(100) == false) {
            Application->ProcessMessages();
            continue;
        }

        //int size = IdTCPClient1->IOHandler->InputBuffer->Size;

        rcvd = IdTCPClient1->IOHandler->ReadLn();
        String infmsg = L"Received: " + rcvd;
        MessageDlg(infmsg, mtInformation, TMsgDlgButtons() << mbOK, 0);
        break;
    }

    IdTCPClient1->IOHandler->InputBuffer->Clear();
    IdTCPClient1->Disconnect();
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    IdTCPClient1->ConnectTimeout = 2000; // msec
    IdTCPClient1->ReadTimeout = 2000; // msec

    commTCP(/*timeout_msec=*/1000);
}
//---------------------------------------------------------------------------

実行例

A. 相手先がListenしていない

qiita.png

B. 相手先がListenしている, 応答しない

qiita.png

C. 相手先がListenしている, 応答する

qiita.png

備考

  • 接続、送信、受信を一括にしているため、他の処理がブロックされる
  • 受信タイムアウトはGetTickcount()での処理
    • ReadTimeoutを使った処理は未消化

使用ツール

関連記事

余談: 記事消した

苦労して記載した記事を間違って消してしまった。

@ 生きるのが楽しくなる15の習慣 by 日野原重明さん

p81 トーマス・カーライルの名著「フランス革命史」
そこで事件は起こりました。友人の家のお手伝いさんが、それを書き損じの原稿と勘違いし、ストーブで燃やしてしまったのです。
それを知ったカーライルはひどく落胆し、やはり「もう同じものは書けない」と気力も失ってしまったとのことでした。
ところが、彼の妻は立派でした。夫に同情しながらも、きっぱりこう言ったそうです。
「このまま書かないですむくらいなら、最初から書く必要がなかったものなのよ」
カーライルはこの言葉に奮起しました。なぜなら、それはカーライルにとってどんなことをしても書かなければならないテーマだったからです。彼は再び机に向かい、そして誕生した本は、160年以上の年月を経た今なお、世界の名著とたたえられています。

code v0.2 > ReadLn()での受信待ち

ReadLn()において受信タイムアウトを指定できるようだ。

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

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

/*
v0.2 2018/01/11
    - ReadLn()の引数での受信タイムアウト処理
v0.1 2018/01/11
    - whileでの受信タイムアウト処理
*/

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::commTCP(int timeout_msec)
{
    // 1. Connect
    IdTCPClient1->Host = E_ipadr->Text;
    int portNum = StrToIntDef(E_port->Text, -1);
    if (portNum < 0) {
        String wrnmsg = L"Error: Invalid port number:" + E_port->Text;
        MessageDlg(wrnmsg, mtError, TMsgDlgButtons() << mbOK, 0);
        return; // fail to get portNum
    }
    IdTCPClient1->Port = portNum;
    try {
        IdTCPClient1->Connect();
    } catch (...) {
        String wrnmsg = L"Failed to connect to " + E_ipadr->Text;
        MessageDlg(wrnmsg, mtError, TMsgDlgButtons() << mbOK, 0);
        return;
    }

    // 2. send
    String sndTxt = E_sendText->Text;
    IdTCPClient1->IOHandler->WriteLn(sndTxt);

    // 3. receive
    String rcvd;
    rcvd = IdTCPClient1->IOHandler->ReadLn(L"", timeout_msec);
    if (rcvd.Length() > 0) {
        String infmsg = L"Received: " + rcvd;
        MessageDlg(infmsg, mtInformation, TMsgDlgButtons() << mbOK, 0);
    } else {
        String wrnmsg = L"Error: Receive timeout";
        MessageDlg(wrnmsg, mtError, TMsgDlgButtons() << mbOK, 0);

    }

    IdTCPClient1->IOHandler->InputBuffer->Clear();
    IdTCPClient1->Disconnect();
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    IdTCPClient1->ConnectTimeout = 2000; // msec
    IdTCPClient1->ReadTimeout = 2000; // msec

    commTCP(/*timeout_msec=*/1000);
}
//---------------------------------------------------------------------------
7of9
セブンオブナインです。Unimatrix 01の第三付属物 9の7という識別番号です。Star trek Voyagerの好きなキャラクターです。まとめ記事は後日タイトルから内容がわからなくなるため、title検索で見つかるよう個々の記事にしてます。いわゆるBorg集合体の有名なセリフから「お前たち(の知識)を吸収する。抵抗は無意味だ」。Thanks in advance.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away