Victor
控件使用方法详解 - TYbCommDevice
文件收发演示程序 (发送端和接收端都需要运行这个程序,接收端自动进行文件接收)
因为考虑速度和可靠性更重要, 程序采用数据包协议进行大量数据收发。
利用 ReadPackage 和 WritePackage 方法, 可发送和接收任意类型的数据包。
完整的例子:
UnitSendFile.h文件内容 (蓝色为新增内容):
//---------------------------------------------------------------------------
#ifndef UnitSendFileH
#define UnitSendFileH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "YbCommDevice.h"
#include <ActnList.hpp>
#include <StdActns.hpp>
#include <Buttons.hpp>
#include <ComCtrls.hpp>
#include "yb_base.h"
#include "UnitTsData.h"
#include <mmsystem.h>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TYbCommDevice *YbCommDevice1;
TActionList *ActionList1;
TFileOpen *FileOpen1;
TBitBtn *BitBtn1;
TProgressBar *ProgressBar1;
TTimer *Timer1;
TMemo *Memo1;
void __fastcall FileOpen1Accept(TObject *Sender);
void __fastcall YbCommDevice1Package(TObject *Sender,
int NotifyType);
void __fastcall Timer1Timer(TObject *Sender);
private: // User declarations
TRelPath dlpath;
TBinFile sf,df;
bool bUploading;
unsigned char PkgID;
long nBytesToReceive, iReceivingCounter;
__int64 iReceiveFileTime;
void __fastcall ShowInfo(AnsiString s);
int __fastcall UploadReq(AnsiString fname);
int __fastcall UploadFileData(void);
int __fastcall WaitforAnswer(unsigned char Cmd,
unsigned char id);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
|
UnitSendFile.cpp 文件:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "UnitSendFile.h"
#include "yb_base.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "YbCommDevice"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
PkgID = 0;
dlpath.Relative = "download";
nBytesToReceive = 0;
iReceiveFileTime = 0;
bUploading = false;
iReceivingCounter = 0;
TBinFileFuncs::MkDir(AnsiString(dlpath).c_str());
YbCommDevice1->PackageType = cptFrameHeadTail;
YbCommDevice1->PackageSize = 9000; //最大允许发送9000字节的数据包
YbCommDevice1->UsePackage = true;
YbCommDevice1->FrameSettings->FrameHead
= 0xdb; //数据包头
YbCommDevice1->FrameSettings->FrameTail
= 0xde; //数据包尾
YbCommDevice1->FrameSettings->FrameCtrl
= 0xdc; //数据控制符
try
{
YbCommDevice1->Active = true;
}
catch(Exception &e)
{
if(!YbCommDevice1->SettingsDialog(this,true))
Application->Terminate();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ShowInfo(AnsiString s)
{
Memo1->Lines->Add(FormatDateTime("yyyy-mm-dd
hh:nn:ss ",Now())+s);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FileOpen1Accept(TObject *Sender)
{
try
{
bUploading = true;
int nCode = UploadReq(FileOpen1->Dialog->FileName);
if(nCode==0x88)nCode = UploadFileData();
switch(nCode)
{
case 0x88: ShowInfo("发送成功!");
break;
case 0xee: ShowInfo("发送文件错误!");
break;
default : ShowInfo("超时,对方电脑没有反应。");break;
}
}
__finally
{
bUploading = false;
sf.Active = false; //关闭文件
}
}
//---------------------------------------------------------------------------
int __fastcall TForm1::UploadReq(AnsiString fname)
{
sf.FileName = fname;
sf.OpenMode = TBinFile::omRead;
sf.Active = true;
TMyFinfoPkg finf; //发送文件信息数据包
finf.cmd = mpcUpload;
finf.id = PkgID++;
TBinFileFuncs::GetFileName(finf.name, sf.FileName.c_str());
finf.size = sf.Size;
finf.time = sf.Time;
finf.CRC = ~TCRC32().Check(&finf, sizeof(TMyFinfoPkg)-4);
YbCommDevice1->WritePackage(&finf, sizeof(TMyFinfoPkg));
ShowInfo("发送文件: "+sf.FileName);
return WaitforAnswer(finf.cmd, finf.id);
}
//---------------------------------------------------------------------------
int __fastcall TForm1::UploadFileData(void)
{
TMyFdataPkg fdata; //发送文件内容数据包
long nFileSize = sf.Size, nTries;
fdata.cmd = mpcFileData; //发送文件数据
fdata.from = 0; //从文件第0个字节开始发送
while((fdata.size=sf.Read(fdata.data,DataSize))>0)
{
fdata.id = PkgID++;
fdata.CRC = ~TCRC32().Check(&fdata,sizeof(TMyFdataPkg)-4);
for(nTries=2; nTries>0; nTries--)
{
YbCommDevice1->WritePackage(&fdata,sizeof(TMyFdataPkg));
if(WaitforAnswer(fdata.cmd,
fdata.id)==0x88)
break;
}
if(!nTries)
{
return 0xee;
}
fdata.from += fdata.size;
ProgressBar1->Position =
TBinFileFuncs::MakePercent(fdata.from, nFileSize);
}
return 0x88;
}
//---------------------------------------------------------------------------
int __fastcall TForm1::WaitforAnswer(unsigned char Cmd, unsigned
char id)
{
TMyStatusPkg AnsPkg; //对方电脑回应的数据包
int tm_start=timeGetTime(), tm_out=2000;
while((int)(timeGetTime()-tm_start)<tm_out)
{
if(YbCommDevice1->ReadPackage(&AnsPkg,sizeof(TMyStatusPkg))==sizeof(TMyStatusPkg))
if((AnsPkg.cmd==mpcStatus) &&
(AnsPkg.id==id) && (AnsPkg.anscmd==Cmd))
{
if(AnsPkg.status
== 0x88)
return
0x88; //ok
return 0xee;
//error
}
Application->ProcessMessages();
}
return 0; //timeout
}
//---------------------------------------------------------------------------
void __fastcall TForm1::YbCommDevice1Package(TObject *Sender,
int NotifyType)
{
if((NotifyType==EV_RXCHAR) && !bUploading)
{
typedef union
{
TMyFinfoPkg
finfo; //文件信息数据包
TMyFdataPkg
fdata; //文件内容数据包
unsigned char
cmd; //无论哪种数据包,第一个字节都是命令字节
} TMyPackage;
TMyPackage recv; //收到的数据包可能是文件信息或者文件内容
TMyStatusPkg send; //发送回应状态数据包
int nReceived; //收到的字节数
while((nReceived=YbCommDevice1->ReadPackage(&recv,sizeof(TMyPackage)))>4)
//数据包的长度都大于4
{
if(recv.cmd==mpcUpload)
{
send.cmd
= mpcStatus;
send.id
= recv.finfo.id;
send.anscmd
= recv.finfo.cmd;
send.status
= (recv.finfo.CRC == ~TCRC32().Check(&recv,nReceived-4))?0x88:0xee;
send.CRC
= ~TCRC32().Check(&send,sizeof(TMyStatusPkg)-4);
if(send.status==0x88)
//数据 CRC 校验正确
{
iReceivingCounter
= 5; //超过5秒没有数据,认为超时,中断接收
nBytesToReceive
= recv.finfo.size;
iReceiveFileTime
= recv.finfo.time;
df.FileName
= dlpath.FileName(recv.finfo.name);
df.OpenMode
= TBinFile::omCreateNew;
df.Active
= true;
ShowInfo("接收文件:
"+df.FileName);
if(nBytesToReceive<=0)
{
df.Time
= iReceiveFileTime;
df.Active
= false;
ShowInfo("接收完成!");
}
}
YbCommDevice1->WritePackage(&send,sizeof(TMyStatusPkg));
}
else if(recv.cmd==mpcFileData)
{
send.cmd
= mpcStatus;
send.id
= recv.fdata.id;
send.anscmd
= recv.fdata.cmd;
send.status
= recv.fdata.CRC == ~TCRC32().Check(&recv,nReceived-4)?0x88:0xee;
send.CRC
= ~TCRC32().Check(&send,sizeof(TMyStatusPkg)-4);
if((send.status==0x88)
&& (df.Active)) //数据 CRC 校验正确
{
iReceivingCounter
= 5; //超过5秒没有数据,认为超时,中断接收
df.Pos
= recv.fdata.from;
df.Write(recv.fdata.data,recv.fdata.size);
if(recv.fdata.from+recv.fdata.size>=nBytesToReceive)
{
df.Time
= iReceiveFileTime;
df.Active
= false;
ShowInfo("接收完成!");
}
ProgressBar1->Position
= TBinFileFuncs::MakePercent(recv.fdata.from+recv.fdata.size,nBytesToReceive);
}
YbCommDevice1->WritePackage(&send,sizeof(TMyStatusPkg));
}
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
if(iReceivingCounter>0)
if(--iReceivingCounter==0)
{
if(df.Active)
{
df.Time =
iReceiveFileTime;
df.Active
= false;
ShowInfo("超时,接收中断。");
}
}
}
//---------------------------------------------------------------------------
|
程序使用的数据结构:
//---------------------------------------------------------------------------
#ifndef UnitTsDataH
#define UnitTsDataH
//---------------------------------------------------------------------------
#include "yb_base.h"
//---------------------------------------------------------------------------
const DataSize=8192;
#pragma pack(push,1)
enum TMyPkgCmd
{
mpcUpload = 1,
mpcFileData = 2,
mpcStatus = 3,
};
typedef struct
{
unsigned char cmd; //1 (1: upload, 2: filedata,
3:status)
unsigned char id;
__int64 time; //date & time
long size; //filesize
char name[MAXPATH]; //filename
unsigned long CRC;
} TMyFinfoPkg;
typedef struct
{
unsigned char cmd; //2 (1: upload, 2: filedata,
3:status)
unsigned char id;
long from;
long size;
char data[DataSize];
unsigned long CRC;
} TMyFdataPkg;
typedef struct
{
unsigned char cmd; //3
unsigned char id;
unsigned char anscmd;
unsigned char status; //0x88: OK
unsigned long CRC;
} TMyStatusPkg;
#pragma pack(pop)
//---------------------------------------------------------------------------
#endif
|
返回
TYbCommDevice
|