副标题#e#
一. 媒介
今朝网络编程技能有许多,一般都是直接操作编程软件自带的成果函数或控件来完成,用户不必体贴低层的操纵,确实带来利便。但机动性不足,假如要传输的文件较量大,则速度慢。假如网络的断线率高,则不得不从头传输。本措施可以降服以上不敷,将任意巨细的文件视网络状况在客户端支解成任意巨细的数据流举办发送,在处事端吸收数据流,并组装成原文件。假如网络被间断,则记下位置,待网络规复后继承从断点的位置传输,终端继承吸收,直到传输完毕。
本措施在Windows2000调试通过,读者可以应用本措施的设计技能应用到其他网络通讯中去。
二.成立措施框架
新建一个工程存为tongxun.bpr,Form文件存为shi.cpp,对Form的属性做如下修改:BorderStyle设为bsSingle,Name设为Form,Position设为PoScreenCenter。在Form上安排2个Tbutton组件,别离为:Name别离为Button1和Button2,Caption别离为"发送图片"和"选择图片文件",安排1个Timage组件,Name为Image1,安排1个Opendialog,Name为name,用于打开1个文件,最后安排1个TserverSocket和1个Tclientsocket,Name属性别离为server和client。
这样就完成了措施框架的成立,如图示:
三.措施实现
本措施是在客户端发送一个2M字节的BMP图片,终端吸收和组装此图片并显示在Form的窗口顶用于验证。本措施即可作为发送端,也可做吸收端,只要在两台互联的计较机上运行即可。
shi.cpp源文件如下:
#include
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
static int shi=0,emod=0,hui=0,x=0,a=0,i=0;
AnsiString filename;
file://---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{ }
file://---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{ client->Active=false;
client->Port=8888;
client->Active=true;} file://联接长途计较机
file://---------------------------------------------------------------------------
void __fastcall TForm1::clientConnect(TObject *Sender,TCustomWinSocket *Socket)
{ label->Caption="ok";} file://联接乐成的提示。
file://下面的函数用于吸收数据和组装数据并显示。
void __fastcall TForm1::serverClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{ // static long a=0;
static TMemoryStream* pms = new TMemoryStream();
void *z[20000]; file://界说缓冲区巨细
if(shi!=1)
{Socket->ReceiveBuf(z,20000); file://吸收SOCKET中的数据流
pms->Position=a;
pms->WriteBuffer(z,20000); file://写入缓冲区
a=a+20000; file://改变内存流指针
client->Active=false; file://每次发送前要判定网络是否流畅
client->Port=8888; file://联接长途计较机,假如乐成则
client->Active=true;} file://发送,不然期待。
Else file://吸收最后emod个字节。
{pms->WriteBuffer(z,emod);
pms->SaveToFile("d:\\k.bmp");
label->Caption="successful";
pms->Position=0;
Image1->Picture->Bitmap->LoadFromStream(pms);}
} file://将吸收的文件在屏幕上显示。
#p#副标题#e#
(图2)发送前
(图3)吸收后显示
file://以下函数用于任意支解文件和发送文件。
void __fastcall TForm1::clientWrite(TObject *Sender,TCustomWinSocket *Socket)
{ void *p[20000];
static long k=20000;//x=0;//hui=0;
static long bmpsize,/*i=0*/c,mod;
static TMemoryStream* pms = new TMemoryStream();
if(hui==0){pms->LoadFromFile(filename);hui++;}//装入要发送的文件。
bmpsize=pms->Size; file://计较文件的巨细(字节)
c=(int)bmpsize/k; file://支解文件为c
mod=bmpsize%k; file://支解后于下的字节数
emod=mod; file://使mod在整个措施都可会见
if(i {pms->Position=x; file://改变内存流读取指针
pms->ReadBuffer(p,k); file://把内存流读入缓冲区,即改变流的范例
x=x+k;
client->Socket->SendBuf(p,k); file://将支解的文件发送
i++; }
else
{ shi++;
if(shi==1)
{pms->ReadBuffer(p,mod); file://发送最后mod个字节后,发送完毕
client->Socket->SendBuf(p,mod); }}}
//下面函数用于选择要发送的文件(*.bmp)
void __fastcall TForm1::Button2Click(TObject *Sender)
{ if(OpenDialog1->Execute()){
filename = OpenDialog1->FileName;
label->Caption="选择图片乐成";
hui=0; shi=0; a=0;
x=0; i=0;}}
file://---------------------------------------------------------------------------
由于在文件中要用到全局变量gan,所以要在unit.h的头文件中插手其界说,如下:
class TForm1 : public TForm
{private: …
TMemoryStream* gan;
…};
四.技能要害
#p#分页标题#e#
把文件举办支解成一块一块的内存流,由于c++builder的套接字Socket在发送吸收时是以缓冲区范例的为数据,因此需要把内存流转化成此范例数据传输。为了使在网络断线时生存断点,用了全局变量和函数内部的静态变量巧妙的办理了这个问题。