多线程网络传输客户端.docx

上传人:b****6 文档编号:4662929 上传时间:2022-12-07 格式:DOCX 页数:16 大小:18.18KB
下载 相关 举报
多线程网络传输客户端.docx_第1页
第1页 / 共16页
多线程网络传输客户端.docx_第2页
第2页 / 共16页
多线程网络传输客户端.docx_第3页
第3页 / 共16页
多线程网络传输客户端.docx_第4页
第4页 / 共16页
多线程网络传输客户端.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

多线程网络传输客户端.docx

《多线程网络传输客户端.docx》由会员分享,可在线阅读,更多相关《多线程网络传输客户端.docx(16页珍藏版)》请在冰豆网上搜索。

多线程网络传输客户端.docx

多线程网络传输客户端

unitUnit1;

interface

uses

Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

Dialogs,ComCtrls,ExtCtrls,StdCtrls,IdBaseComponent,IdComponent,

IdTCPConnection,IdTCPClient,Unit2;

const

packsize=65000;//包大小

type

TRevBuffer=packedrecord

masmID:

Word;//未用

ID:

Word;//标记

F1:

DWord;

F2:

DWord;

F3:

DWord;

F4:

DWord;

Len:

DWord;

MD:

Int64;

end;

TSendBuffer=packedrecord

masmID:

Word;//未用

ID:

Word;//标记

F1:

DWord;

F2:

DWord;

F3:

DWord;

F4:

DWord;

Len:

DWord;//数据区的大小

MD:

Int64;//摘要

buffer:

Array[0..packsize-1]ofbyte;

end;

//性能监测线程

type

TMonitorThread=class(TThread)

private

SecondTimer:

DWord;

protected

procedureExecute;override;

public

constructorCreate();reintroduce;

end;

type

TFeiler=class;

TSocketThread=class(TThread)

private

Rev:

TRevBuffer;

Snd:

TSendBuffer;

PRev,PSnd,TP,UP:

PByte;

TempPointer:

PByte;

RemainBytes:

Word;

ReceivedCounter:

Integer;

HeaderFinished,BodyFinished,PushTransporting:

Boolean;

FeilerThread:

TFeiler;

MyIndex:

Integer;

FClient:

TIdTCPClient;

SendBytes:

DWord;//该线程要传输的字节数

MapOffset:

DWord;//文件映像指针偏移

FileMapPointer:

PByte;//内存映像文件指针

SendBlock:

DWord;//该线程要传输的块数

Thread_H,Thread_T:

DWord;

procedureProcess;

procedureBranch;

procedureRequestTransfer;

procedureServerReady;

proceduretransporting;

protected

procedureExecute;override;

public

constructorCreate(F:

TFeiler;Index:

Integer;Offset:

DWord;Count:

DWord;FileMap:

PByte);reintroduce;

end;

TFeiler=class(TForm)

Edit1:

TEdit;

ComboBox1:

TComboBox;

Button1:

TButton;

Button2:

TButton;

Edit2:

TEdit;

OpenDialog1:

TOpenDialog;

Label1:

TLabel;

Label2:

TLabel;

Label3:

TLabel;

Button3:

TButton;

Panel1:

TPanel;

StatusBar1:

TStatusBar;

procedureButton2Click(Sender:

TObject);

procedureButton1Click(Sender:

TObject);

procedureButton3Click(Sender:

TObject);

procedureFormClose(Sender:

TObject;varAction:

TCloseAction);

private

{Privatedeclarations}

public

FileSize:

DWord;//要传输的文件大小

SocketThread:

ArrayofTSocketThread;

Event:

ArrayofTHandle;

Instructor:

ArrayofTProgressBar;

MonitorThread:

TMonitorThread;

MP:

PByte;

{Publicdeclarations}

end;

var

Feiler:

TFeiler;

ShowProgress:

Boolean;

HeightInc:

Integer;

implementation

{$R*.dfm}

constructorTSocketThread.Create(F:

TFeiler;Index:

Integer;Offset:

DWord;Count:

DWord;FileMap:

PByte);

var

Iswork:

Boolean;

begin

FeilerThread:

=F;

MyIndex:

=Index;

MapOffset:

=Offset;

SendBytes:

=Count;

FileMapPointer:

=FileMap;

INC(FileMapPointer,Offset);

SentBytes[MyIndex]:

=0;

IFIndex=0then

Iswork:

=False

else

Iswork:

=True;

ReceivedCounter:

=32;

PRev:

=@Rev;PSnd:

=@Snd;TempPointer:

=PRev;

inheritedCreate(IsWork);

end;

procedureTSocketThread.Execute;

var

H,I,J:

Integer;

Thread_L:

Integer;

CurPointerOffset:

DWord;

File_Name:

String[250];

begin

FClient:

=TIdTCPClient.Create(nil);

FClient.Host:

=FeilerThread.Edit1.Text;

FClient.Port:

=60606;

try

FClient.Connect(10000);

except

//错误处理

Application.MessageBox('无法连接服务器','ERROR',MB_ICONERROR);

FClient.Free;

exit;

end;

//**接收服务器信息**//

Thread_H:

=(SendBytes-1)divpacksize+1;//需要传输Thread_H个数据块

Thread_T:

=SendBytes-(Thread_H-1)*packsize;//尾巴

FeilerThread.Instructor[MyIndex].Max:

=Thread_H;

Snd.F2:

=Thread_H;

IFMyIndex=0then//0号线程负责初始化服务器

begin

Snd.ID:

=0;//通知服务器建立文件

TP:

=PSnd;Inc(TP,32);

File_name:

=ExtractFileName(FeilerThread.Edit2.Text);

Snd.Len:

=Length(File_name)+1;

Snd.F1:

=FeilerThread.FileSize;

UP:

=@File_name;

move(UP^,TP^,Snd.Len);

FClient.Socket.Send(PSnd^,Snd.Len+32);//通知服务器

repeat

process;

untilRev.ID=3;//Snd.F1=Snd.F2;

SentBytes[MyIndex]:

=SentBytes[MyIndex]+Snd.Len;//最后一个尾巴

H:

=Length(FeilerThread.Event);

IFH>1then//2个线程以上的话

WaitForMultipleObjects(H-1,@FeilerThread.Event[1],True,INFINITE);

Feiler.MonitorThread.Terminate;

Snd.ID:

=3;//告知服务器关闭内存影像

Snd.Len:

=0;

FClient.Socket.Send(PSnd^,32);

UnMapViewOfFile(FeilerThread.MP);//关闭内存映像

ForI:

=0toH-1do

CloseHandle(FeilerThread.Event[I]);

SetLength(FeilerThread.Event,0);

FeilerThread.Button1.Enabled:

=True;

end

else

begin

RequestTransfer;

repeat

process;

untilRev.ID=3;//Snd.F1=Snd.F2;

SentBytes[MyIndex]:

=SentBytes[MyIndex]+Snd.Len;

SetEvent(FeilerThread.Event[MyIndex]);

end;

FClient.Disconnect;

end;

procedureTFeiler.Button2Click(Sender:

TObject);

var

F:

Tsearchrec;

begin

IFOpenDialog1.Executethen

Edit2.Text:

=OpenDialog1.FileName;

IFFindFirst(Edit2.Text,FaAnyfile,F)=0then

FileSize:

=F.Size;

end;

procedureTFeiler.Button1Click(Sender:

TObject);

var

H,I,J,K,U:

Integer;

FH,MH:

THandle;

begin

//建立文件内存映像

Button1.Enabled:

=False;

FH:

=FileOpen(Edit2.Text,fmOpenRead);

MH:

=CreateFileMapping(FH,nil,Page_ReadOnly,0,FileSize,nil);

CloseHandle(FH);

MP:

=MapViewOfFile(MH,File_Map_Read,0,0,FileSize);

CloseHandle(MH);

J:

=strtoint(ComboBox1.Text);

I:

=(FileSize-1)div(1024*1024)+1;//最多线程数

IFJ>Ithen

J:

=I;

//一共有J个线程

//建立进度指示

ThreadCount:

=J;

ForK:

=0toLength(Instructor)-1do

Instructor[K].Free;

SetLength(Instructor,J);

SetLength(SentBytes,J);

ForK:

=0toJ-1do

begin

Instructor[K]:

=TProgressBar.Create(self);

Instructor[K].Left:

=0;

Instructor[K].Top:

=K*16;

Instructor[K].Width:

=390;

Instructor[K].Step:

=1;

Instructor[K].Parent:

=Panel1;

end;

I:

=FileSizedivJ;//每个线程的传输字节

K:

=FileSize-I*J;//最后一个线程要多传输的字节,尾巴

U:

=I;

SetLength(SocketThread,J);

SetLength(Event,J);

ForH:

=0toJ-1do

begin

IFH=J-1then

I:

=I+K;//最后的数据块

SocketThread[H]:

=TSocketThread.Create(self,H,H*U,I,MP);

Event[H]:

=CreateEvent(nil,False,False,nil);

end;//循环结束

end;

procedureTSocketThread.Branch;

begin

caseRev.IDof

1:

ServerReady;

2:

transporting;

end;

end;

procedureTSocketThread.RequestTransfer;

begin

Snd.ID:

=1;

Snd.F1:

=0;

Snd.Len:

=0;

FClient.Socket.Send(PSnd^,32);

end;

procedureTSocketThread.Process;

var

Bytes:

Integer;

begin

IFRemainBytes>0then//上次还有字节没收取

begin

ReceivedCounter:

=ReceivedCounter-RemainBytes;

IFReceivedCounter>0then//接收剩余字节后数据报尚未完成接收

begin

Bytes:

=RemainBytes;//接收剩余

RemainBytes:

=0;

end

else

begin

IFReceivedCounter=0then//剩余字节刚好接收完成

begin

Bytes:

=RemainBytes;

RemainBytes:

=0;

IFHeaderFinishedthen

BodyFinished:

=True

else

begin

HeaderFinished:

=True;//如果头完成就是体完成,否则只是头完成

PushTransporting:

=True;

end;

end

else

begin//剩余字节超过本数据报大小,产生数据粘连

Bytes:

=ReceivedCounter+RemainBytes;

RemainBytes:

=RemainBytes-Bytes;//完成本数据报后剩余字节

IFHeaderFinishedthen

BodyFinished:

=True

else

begin

HeaderFinished:

=True;//如果头完成就是体完成,否则只是头完成

PushTransporting:

=True;

end;

end;

end;

FClient.ReadBuffer(TempPointer^,Bytes);

Inc(TempPointer,Bytes);

IF(Rev.Len=0)andHeaderFinishedthen//只要头

begin

HeaderFinished:

=False;

PushTransporting:

=False;

TempPointer:

=PRev;

ReceivedCounter:

=32;//准备下一个头

Branch;//分支处理

end

else

begin

IFPushTransportingthen//正在传输body

begin

PushTransporting:

=False;

ReceivedCounter:

=Rev.Len;

end

else

IFBodyFinishedthen

begin

TempPointer:

=PRev;

HeaderFinished:

=False;

BodyFinished:

=False;

ReceivedCounter:

=32;//准备下一个头

Branch;//分支处理

end

end;

end

else

begin//RemainBytes=0

Try

RemainBytes:

=FClient.ReadFromStack(True,15000,True);

Except

exit;

end;

end;

end;

procedureTSocketThread.ServerReady;

var

H:

Integer;

begin

ForH:

=2tostrtoint(Feiler.ComboBox1.Text)do

Feiler.SocketThread[H-1].Resume;

RequestTransfer;

Feiler.MonitorThread:

=TMonitorThread.Create;

end;

procedureTSocketThread.transporting;

var

FTT,FUU:

PByte;

begin

SentBytes[MyIndex]:

=SentBytes[MyIndex]+Snd.Len;//已发送字节

Snd.ID:

=2;

Snd.F1:

=Rev.F1;

IFSnd.F1=Snd.F2then

Snd.Len:

=Thread_T

else

Snd.Len:

=packsize;

Snd.F3:

=MapOffset+(Snd.F1-1)*packsize;

FTT:

=FileMapPointer;

INC(FTT,(Snd.F1-1)*packsize);

FUU:

=PSnd;Inc(FUU,32);

move(FTT^,FUU^,Snd.Len);

FClient.Socket.Send(PSnd^,Snd.Len+32);

FeilerThread.Instructor[MyIndex].StepIt;

end;

procedureTFeiler.Button3Click(Sender:

TObject);

begin

IFNot(ShowProgress)then

Button3.Caption:

='<<进度显示'

else

Button3.Caption:

='进度显示>>';

ShowProgress:

=Not(ShowProgress);

IFShowProgressthen

begin

HeightInc:

=strtoint(ComboBox1.Text)*20;

Feiler.Height:

=Feiler.Height+HeightInc;

end

else

begin

Feiler.Height:

=Feiler.Height-HeightInc;

end;

end;

{TMonitorThread}

constructorTMonitorThread.Create;

begin

SecondTimer:

=0;

inheritedCreate(false);

end;

procedureTMonitorThread.Execute;

var

H,I,V:

DWord;

begin

WhileNot(Terminated)do

begin

Sleep(1000);

SecondTimer:

=SecondTimer+1;

H:

=0;

ForI:

=0toThreadCount-1do

H:

=H+SentBytes[I];

V:

=HdivSecondTimer;

V:

=Vdiv1024;

Feiler.StatusBar1.Panels[2].Text:

='平均速率:

'+Inttostr(V)+'KB/S';

end;

end;

procedureTFeiler.FormClose(Sender:

TObject;varAction:

TCloseAction);

var

K:

Integer;

begin

ForK:

=0toLength(Instructor)-1do

Instructor[K].Free;

SetLength(Instructor,0);

SetLength(SentBytes,0);

SetLength(SocketThread,0);

SetLength(Event,0);

end;

end.

unitUnit1;

interface

uses

Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

Dialogs,StdCtrls,SocketProcess,IdBaseComponent,IdComponent,

IdTCPServer;

type

TForm1=class(TForm)

Button1:

TButton;

IdTCPServer1:

TIdTCPServer;

Memo1:

TMemo;

Button2:

TButton;

procedureIdTCPServer1Connect(AThread:

TIdPeerThread);

procedureIdTCPServer1Disconnect(AThread:

TIdPeerThread);

procedureIdTCPServer1Execute(AThread:

TIdPeerThread);

procedureButton1Click(Sender:

TObject);

procedureFormClose(Sender:

TObject;varAction:

TCloseAction);

procedureButton2Click(Sender:

TObject);

private

{Privatedeclarations}

public

{Publicdeclarations}

end;

var

Form1:

TForm1;

Lock_exe:

TRTLCriticalSection;

implementation

{$R*.dfm}

procedureTForm1.IdTCPServer1Connect(AThread:

TIdPeerThread);

var

DoP:

TSocketProcesser;

begin

DoP:

=TSocketProcesser.Create(AThrea

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 可爱清新

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1