N
NeverMind
Unregistered / Unconfirmed
GUEST, unregistred user!
client端:
type
TClientThread = class(TThread)
private
{ Private declarations }
IP: string;
PortNo: integer;
SendFile: string;
ClientSocket: TClientSocket;
reConnectTime: integer;
iPackID: integer;
iLeftSize: integer;
PackCount: integer;
fileStream: TFileStream;
protected
procedure Execute; override;
procedure SetReConnectTime(Time: integer);
public
constructor Create(CreateSuspended: Boolean;HostIP: string;HostPort: integer;FileName: string);
destructor Destory;
procedure ClientSocketError(Sender: TObject;Socket: TCustomWinSocket;ErrorEvent: TerrorEvent; var ErrorCode: Integer);
procedure ClientSocketConnect(Sender: TObject;Socket: TCustomWinSocket);
procedure ClientSocketOnRead(Sender: TObject;Socket: TCustomWinSocket);
function Open: Boolean;
function GetPackCount(var FileName:String):Integer;
procedure UpdateData(var iLeftSize: integer; DataPack: TPackRecord);
property ConnectTime: integer read reConnectTime write SetReConnectTime;
end;
implementation
procedure TClientThread.ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
PackHead: TPackHead;
begin
ClientSocket.Active := True;
PackHead.PackType := ptFirst;
PackHead.ThreadID := Self.ThreadID;
PackHead.FileName := Copy(SendFile,StringLocation('/',SendFile)+1,Length(SendFile)-StringLocation('/',SendFile)+1);
PackHead.PackCount := PackCount;
ClientSocket.Socket.SendBuf(PackHead,SizeOf(PackHead));
end;
procedure TClientThread.ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TerrorEvent;
var ErrorCode: Integer);
begin
ClientSocket.Close;
ErrorCode := 0;
end;
procedure TClientThread.ClientSocketOnRead(Sender: TObject;
Socket: TCustomWinSocket);
var
Protocol: TProtocols;
Command: TProtocol;
DataPack: TPackRecord;
begin
while (not Terminated) and (not suspended) do
begin
Protocol := [START,NEXT,OVER];
DelayTime(10);
Socket.ReceiveBuf(Command,Socket.ReceiveLength);
if (Command in Protocol) and (SendFile <> '') then
begin
case Command of
START: begin
fileStream := TFileStream.Create(SendFile,fmOpenRead,fmShareDenyWrite);
iLeftSize := fileStream.Size;
end;
OVER: begin
ClientSocket.Close;
Terminate;
Destory;
end;
end;
UpdateData(iLeftSize,DataPack);
end;
end;
end;
constructor TClientThread.Create(CreateSuspended: Boolean; HostIP: string;
HostPort: integer;FileName: string);
begin
inherited create(true);
FreeOnTerminate := True;
ClientSocket := TClientSocket.Create(nil);
IP := HostIP;
PortNo := HostPort;
with ClientSocket do
begin
Address := IP;
Port := PortNo;
ClientType := ctNonBlocking;
OnError := ClientSocketError;
OnConnect := ClientSocketConnect;
OnRead := ClientSocketOnRead;
end;
SendFile := FileName;
PackCount := GetPackCount(SendFile);
end;
procedure TClientThread.SetReConnectTime(Time: integer);
begin
if ReConnectTime <> Time then
ReConnectTime := Time;
end;
procedure TClientThread.Execute;
begin
Open;
end;
function TClientThread.Open: Boolean;
var
i: integer;
begin
i := 0;
while i < reConnectTime do
begin
ClientSocket.Open;
DelayTime(150);
if ClientSocket.Active then
Break;
inc(i);
end;
result := ClientSocket.Active;
end;
destructor TClientThread.Destory;
begin
ClientSocket.Free;
fileStream.Free;
inherited free;
end;
function TClientThread.GetPackCount(var FileName: String): Integer;
var
Stream: TFileStream;
begin
Stream := TFileStream.Create(FileName,fmOpenRead,fmShareDenyWrite );
if (Stream.Size mod CACHESIZE) <> 0 then
PackCount := (Stream.Size div CACHESIZE)+1
else
PackCount := Stream.Size div CACHESIZE;
Stream.Free;
result := PackCount;
end;
procedure TClientThread.UpdateData(var iLeftSize: integer;DataPack: TPackRecord);
begin
if iLeftSize <= CACHESIZE then
begin
with DataPack do
begin
PackType := ptLast;
Size := iLeftSize;
PackID := iPackID+1;
fileStream.Read(Cache,iLeftSize);
iLeftSize := 0;
end;
end
else
begin
with DataPack do
begin
PackType :=ptNormal;
Size :=CACHESIZE;
PackID :=iPackID+1;
Inc(iPackID);
fileStream.Read(Cache,CACHESIZE);
iLeftSize:=iLeftSize - CACHESIZE;
end;
end;
ClientSocket.Socket.SendBuf(DataPack,SizeOf(DataPack));
//DelayTime(100);
end;
//*************************************************************************//
Server端
type
TServerThread = class(TServerClientThread)
private
{ Private declarations }
ReceiveFileName :String;
fileStream :TFileStream;
iPackID :cardinal;
protected
//procedure Execute; override;
procedure ClientExecute;override;
public
Constructor Create(CreateSuspended:Boolean;ASocket:TServerClientWinSocket);virtual;
destructor Destory;virtual;
procedure OnAccept;
procedure ClientRead;
//function StartConnect: Boolean;virtual;
end;
implementation
procedure TServerThread.ClientExecute;
var
Stream : TWinSocketStream;
begin
while not Terminated and ClientSocket.Connected do
begin
try
Stream := TWinSocketStream.Create(ClientSocket, 60000);
try
if Stream.WaitForData(60000) then
begin
OnAccept;
fileStream := TFileStream.Create('d:/'+ReceiveFileName,fmCreate,fmShareExclusive);
ClientRead;
Destory;
end
else
ClientSocket.Close;
finally
Stream.Free;
end;
except
HandleException;
end;
end;
end;
procedure TServerThread.ClientRead;
var
PackType :TPackTypes;
DataRecord :TPackRecord;
Protocol :TProtocol;
begin
while not terminated and ClientSocket.Connected do
begin
PackType :=[ptNormal,ptLast];
ClientSocket.ReceiveBuf(DataRecord,ClientSocket.ReceiveLength);
if (DataRecord.PackType in PackType) and (DataRecord.PackID = iPackID+1) then
begin
fileStream.Write(DataRecord.Cache,DataRecord.Size);
case DataRecord.PackType of
ptNormal:
begin
iPackID :=DataRecord.PackID;
Protocol :=NEXT;
ClientSocket.SendBuf(Protocol,SizeOf(Protocol));
end;
ptLast:
begin
Protocol :=OVER;
Sleep(50);
ClientSocket.SendBuf(Protocol,SizeOf(Protocol));
DelayTime(100);
self.Destory;
end;
end;
end;
end;
end;
constructor TServerThread.Create(CreateSuspended: Boolean;ASocket: TServerClientWinSocket);
begin
inherited Create(false,ASocket);
FreeOnTerminate := True;
end;
destructor TServerThread.Destory;
begin
Terminate;
fileStream.Free;
inherited free;
end;
procedure TServerThread.OnAccept;
var
MainPack :TPackHead;
Command :TProtocol;
PackType :TPackTypes;
begin
ClientSocket.ReceiveBuf(MainPack,ClientSocket.ReceiveLength);
PackType :=[ptFirst];
if MainPack.PackType in PackType then
begin
ReceiveFileName :=MainPack.FileName;
Command :=START;
ClientSocket.SendBuf(Command,SizeOf(Command));
end;
end;
end.
//**************************************************************************//
公用部分
const CACHESIZE=1024; //若不是1024,则在测试传送文本时产生乱码,不解!---问题2
type
TProtocol = (START,NEXT,OVER);
TProtocols = set of TProtocol;
TPackType = (ptFirst,ptNormal,ptLast);
TPackTypes = set of TPackType;
TNetStatus = (nsNone,nsConnected,nsConnectFail,nsTransOver);
TPackRecord = packed record
PackType :TPackType;
Size :Integer;
PackID :Cardinal;
Cache :Array [1..CACHESIZE] of Char;
end;
type
TPackHead = packed Record
PackType :TPackType;
ThreadID :Integer;
FileName :String[255];
PackCount :Integer;
end;
var
tsThread: TList;
CS: TRTLCriticalSection;
hMutex: THandle = 0;
procedure DelayTime(_T :Cardinal);
function StringLocation(strTraget:string;strSource:string):Integer;
implementation
procedure DelayTime(_T:Cardinal);
var
StartTime :Cardinal;
begin
StartTime :=GetTickCount;
while (GetTickCount-StartTime) < _T do
Application.ProcessMessages;
end;
function StringLocation(strTraget:string;strSource:string):Integer;
var
iIndex:Integer;
begin
iIndex:=Length(strSource)-1;
while strTraget<>strSource[iIndex] do
begin
iIndex := iIndex -1 ;
end;
if strTraget=strSource[iIndex] then
Result:=iIndex
else
Result:=-1;
end;
end.
呵呵,东西多了点,让大伙看着受累了!我现在就是单文件传送,都很不稳定:1.)传送文件,有时候成功,有时候不成功;2.)见公用部分第一行;3.)传送速度慢!
盼高人相助,不胜感激!
type
TClientThread = class(TThread)
private
{ Private declarations }
IP: string;
PortNo: integer;
SendFile: string;
ClientSocket: TClientSocket;
reConnectTime: integer;
iPackID: integer;
iLeftSize: integer;
PackCount: integer;
fileStream: TFileStream;
protected
procedure Execute; override;
procedure SetReConnectTime(Time: integer);
public
constructor Create(CreateSuspended: Boolean;HostIP: string;HostPort: integer;FileName: string);
destructor Destory;
procedure ClientSocketError(Sender: TObject;Socket: TCustomWinSocket;ErrorEvent: TerrorEvent; var ErrorCode: Integer);
procedure ClientSocketConnect(Sender: TObject;Socket: TCustomWinSocket);
procedure ClientSocketOnRead(Sender: TObject;Socket: TCustomWinSocket);
function Open: Boolean;
function GetPackCount(var FileName:String):Integer;
procedure UpdateData(var iLeftSize: integer; DataPack: TPackRecord);
property ConnectTime: integer read reConnectTime write SetReConnectTime;
end;
implementation
procedure TClientThread.ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
PackHead: TPackHead;
begin
ClientSocket.Active := True;
PackHead.PackType := ptFirst;
PackHead.ThreadID := Self.ThreadID;
PackHead.FileName := Copy(SendFile,StringLocation('/',SendFile)+1,Length(SendFile)-StringLocation('/',SendFile)+1);
PackHead.PackCount := PackCount;
ClientSocket.Socket.SendBuf(PackHead,SizeOf(PackHead));
end;
procedure TClientThread.ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TerrorEvent;
var ErrorCode: Integer);
begin
ClientSocket.Close;
ErrorCode := 0;
end;
procedure TClientThread.ClientSocketOnRead(Sender: TObject;
Socket: TCustomWinSocket);
var
Protocol: TProtocols;
Command: TProtocol;
DataPack: TPackRecord;
begin
while (not Terminated) and (not suspended) do
begin
Protocol := [START,NEXT,OVER];
DelayTime(10);
Socket.ReceiveBuf(Command,Socket.ReceiveLength);
if (Command in Protocol) and (SendFile <> '') then
begin
case Command of
START: begin
fileStream := TFileStream.Create(SendFile,fmOpenRead,fmShareDenyWrite);
iLeftSize := fileStream.Size;
end;
OVER: begin
ClientSocket.Close;
Terminate;
Destory;
end;
end;
UpdateData(iLeftSize,DataPack);
end;
end;
end;
constructor TClientThread.Create(CreateSuspended: Boolean; HostIP: string;
HostPort: integer;FileName: string);
begin
inherited create(true);
FreeOnTerminate := True;
ClientSocket := TClientSocket.Create(nil);
IP := HostIP;
PortNo := HostPort;
with ClientSocket do
begin
Address := IP;
Port := PortNo;
ClientType := ctNonBlocking;
OnError := ClientSocketError;
OnConnect := ClientSocketConnect;
OnRead := ClientSocketOnRead;
end;
SendFile := FileName;
PackCount := GetPackCount(SendFile);
end;
procedure TClientThread.SetReConnectTime(Time: integer);
begin
if ReConnectTime <> Time then
ReConnectTime := Time;
end;
procedure TClientThread.Execute;
begin
Open;
end;
function TClientThread.Open: Boolean;
var
i: integer;
begin
i := 0;
while i < reConnectTime do
begin
ClientSocket.Open;
DelayTime(150);
if ClientSocket.Active then
Break;
inc(i);
end;
result := ClientSocket.Active;
end;
destructor TClientThread.Destory;
begin
ClientSocket.Free;
fileStream.Free;
inherited free;
end;
function TClientThread.GetPackCount(var FileName: String): Integer;
var
Stream: TFileStream;
begin
Stream := TFileStream.Create(FileName,fmOpenRead,fmShareDenyWrite );
if (Stream.Size mod CACHESIZE) <> 0 then
PackCount := (Stream.Size div CACHESIZE)+1
else
PackCount := Stream.Size div CACHESIZE;
Stream.Free;
result := PackCount;
end;
procedure TClientThread.UpdateData(var iLeftSize: integer;DataPack: TPackRecord);
begin
if iLeftSize <= CACHESIZE then
begin
with DataPack do
begin
PackType := ptLast;
Size := iLeftSize;
PackID := iPackID+1;
fileStream.Read(Cache,iLeftSize);
iLeftSize := 0;
end;
end
else
begin
with DataPack do
begin
PackType :=ptNormal;
Size :=CACHESIZE;
PackID :=iPackID+1;
Inc(iPackID);
fileStream.Read(Cache,CACHESIZE);
iLeftSize:=iLeftSize - CACHESIZE;
end;
end;
ClientSocket.Socket.SendBuf(DataPack,SizeOf(DataPack));
//DelayTime(100);
end;
//*************************************************************************//
Server端
type
TServerThread = class(TServerClientThread)
private
{ Private declarations }
ReceiveFileName :String;
fileStream :TFileStream;
iPackID :cardinal;
protected
//procedure Execute; override;
procedure ClientExecute;override;
public
Constructor Create(CreateSuspended:Boolean;ASocket:TServerClientWinSocket);virtual;
destructor Destory;virtual;
procedure OnAccept;
procedure ClientRead;
//function StartConnect: Boolean;virtual;
end;
implementation
procedure TServerThread.ClientExecute;
var
Stream : TWinSocketStream;
begin
while not Terminated and ClientSocket.Connected do
begin
try
Stream := TWinSocketStream.Create(ClientSocket, 60000);
try
if Stream.WaitForData(60000) then
begin
OnAccept;
fileStream := TFileStream.Create('d:/'+ReceiveFileName,fmCreate,fmShareExclusive);
ClientRead;
Destory;
end
else
ClientSocket.Close;
finally
Stream.Free;
end;
except
HandleException;
end;
end;
end;
procedure TServerThread.ClientRead;
var
PackType :TPackTypes;
DataRecord :TPackRecord;
Protocol :TProtocol;
begin
while not terminated and ClientSocket.Connected do
begin
PackType :=[ptNormal,ptLast];
ClientSocket.ReceiveBuf(DataRecord,ClientSocket.ReceiveLength);
if (DataRecord.PackType in PackType) and (DataRecord.PackID = iPackID+1) then
begin
fileStream.Write(DataRecord.Cache,DataRecord.Size);
case DataRecord.PackType of
ptNormal:
begin
iPackID :=DataRecord.PackID;
Protocol :=NEXT;
ClientSocket.SendBuf(Protocol,SizeOf(Protocol));
end;
ptLast:
begin
Protocol :=OVER;
Sleep(50);
ClientSocket.SendBuf(Protocol,SizeOf(Protocol));
DelayTime(100);
self.Destory;
end;
end;
end;
end;
end;
constructor TServerThread.Create(CreateSuspended: Boolean;ASocket: TServerClientWinSocket);
begin
inherited Create(false,ASocket);
FreeOnTerminate := True;
end;
destructor TServerThread.Destory;
begin
Terminate;
fileStream.Free;
inherited free;
end;
procedure TServerThread.OnAccept;
var
MainPack :TPackHead;
Command :TProtocol;
PackType :TPackTypes;
begin
ClientSocket.ReceiveBuf(MainPack,ClientSocket.ReceiveLength);
PackType :=[ptFirst];
if MainPack.PackType in PackType then
begin
ReceiveFileName :=MainPack.FileName;
Command :=START;
ClientSocket.SendBuf(Command,SizeOf(Command));
end;
end;
end.
//**************************************************************************//
公用部分
const CACHESIZE=1024; //若不是1024,则在测试传送文本时产生乱码,不解!---问题2
type
TProtocol = (START,NEXT,OVER);
TProtocols = set of TProtocol;
TPackType = (ptFirst,ptNormal,ptLast);
TPackTypes = set of TPackType;
TNetStatus = (nsNone,nsConnected,nsConnectFail,nsTransOver);
TPackRecord = packed record
PackType :TPackType;
Size :Integer;
PackID :Cardinal;
Cache :Array [1..CACHESIZE] of Char;
end;
type
TPackHead = packed Record
PackType :TPackType;
ThreadID :Integer;
FileName :String[255];
PackCount :Integer;
end;
var
tsThread: TList;
CS: TRTLCriticalSection;
hMutex: THandle = 0;
procedure DelayTime(_T :Cardinal);
function StringLocation(strTraget:string;strSource:string):Integer;
implementation
procedure DelayTime(_T:Cardinal);
var
StartTime :Cardinal;
begin
StartTime :=GetTickCount;
while (GetTickCount-StartTime) < _T do
Application.ProcessMessages;
end;
function StringLocation(strTraget:string;strSource:string):Integer;
var
iIndex:Integer;
begin
iIndex:=Length(strSource)-1;
while strTraget<>strSource[iIndex] do
begin
iIndex := iIndex -1 ;
end;
if strTraget=strSource[iIndex] then
Result:=iIndex
else
Result:=-1;
end;
end.
呵呵,东西多了点,让大伙看着受累了!我现在就是单文件传送,都很不稳定:1.)传送文件,有时候成功,有时候不成功;2.)见公用部分第一行;3.)传送速度慢!
盼高人相助,不胜感激!