C++ Builder XE4 > TCP > Client에서 전송 및 수신 처리 > v0.3: TTimer를 통한 수신 재시도
18456 단어 indynetworkAppcppBuilder
C++ Builder XE4
처리 개요
v0.3의 변경점
v0.1, v0.2에서는 commTCP()의 처리에서 수신 완료(또는 타임아웃)까지 처리를 빠뜨리지 않았다.
다른 처리와의 병렬성이 손실된다.
v0.3에서는 다음과 같이 했다.
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>
#include <Vcl.ExtCtrls.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;
TTimer *ReceiveTimer;
void __fastcall Button1Click(TObject *Sender);
void __fastcall ReceiveTimerTimer(TObject *Sender);
private: // ユーザー宣言
void __fastcall commTCP(int timeout_msec);
void __fastcall disconnectTcp(void);
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;
//---------------------------------------------------------------------------
/*
*** 留意事項 (2018/01/11) ***
- [ReceiveTimer]のTagを受信リトライの回数として使用
*/
/*
v0.3 2018/01/11
- TTimerによる受信処理 (リトライ付き)
+ disconnectTcp()追加
+ [ReceiveTimer]追加
v0.2 2018/01/11
- ReadLn()の引数での受信タイムアウト処理
v0.1 2018/01/11
- whileでの受信タイムアウト処理
*/
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ReceiveTimer->Enabled = false;
}
//---------------------------------------------------------------------------
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用TTimerの起動
ReceiveTimer->Tag = 3; // Retry
ReceiveTimer->Interval = 100; // msec
ReceiveTimer->Enabled = true;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdTCPClient1->ConnectTimeout = 2000; // msec
IdTCPClient1->ReadTimeout = 2000; // msec
commTCP(/*timeout_msec=*/1000);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ReceiveTimerTimer(TObject *Sender)
{
// *** InputBufferIsEmpty()使用ではサーバー応答ありでもReadLn()まで到達することはなかった
// if (IdTCPClient1->IOHandler->InputBufferIsEmpty()) {
// ReceiveTimer->Tag -= 1;
// if (ReceiveTimer->Tag == 0) {
// ReceiveTimer->Enabled = false;
// disconnectTcp();
// //
// String wrnmsg = L"Error: Receive timeout";
// MessageDlg(wrnmsg, mtError, TMsgDlgButtons() << mbOK, 0);
// }
// return;
// }
String rcvd = IdTCPClient1->IOHandler->ReadLn(L"", 10); // msec
//String rcvd = IdTCPClient1->IOHandler->ReadLn();
if (rcvd == NULL || rcvd.Length() == 0) {
ReceiveTimer->Tag -= 1;
if (ReceiveTimer->Tag == 0) {
ReceiveTimer->Enabled = false;
disconnectTcp();
//
String wrnmsg = L"Error: Receive timeout";
MessageDlg(wrnmsg, mtError, TMsgDlgButtons() << mbOK, 0);
}
return;
}
ReceiveTimer->Enabled = false;
disconnectTcp();
String infmsg = L"Received: " + rcvd;
MessageDlg(infmsg, mtInformation, TMsgDlgButtons() << mbOK, 0);
}
void __fastcall TForm1::disconnectTcp(void)
{
IdTCPClient1->IOHandler->InputBuffer->Clear();
IdTCPClient1->Disconnect();
}
//---------------------------------------------------------------------------
비고
실행 예
(v0.1, v0.2와 동일)
A. 상대방이 청취하지 않음
B. 상대방이 청취 중, 응답하지 않음
C. 상대방이 청취하고 있다, 응답
사용 도구
NonSoft - TCP/IP 테스트 도구
자작 TCP/IP echo server
관련 기사
Reference
이 문제에 관하여(C++ Builder XE4 > TCP > Client에서 전송 및 수신 처리 > v0.3: TTimer를 통한 수신 재시도), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/7of9/items/79df813461ec68e717ef텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)