to bluely,张无忌:
“ 客户端,用非阻塞的方式就可以了”?我就这样,什么服务器端收到的stream.size是0.
我的代码如下:
客户端:
unit main2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls, ComCtrls;
type
TForm1 = class(TForm)
nmg_objClientSocket: TClientSocket;
Button2: TButton;
Edit1: TEdit;
StatusBar1: TStatusBar;
OpenDialog1: TOpenDialog;
procedure Button2Click(Sender: TObject);
procedure nmg_objClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure nmg_objClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
procedure nmg_objClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
private
stream : TMemoryStream; //定义内存流,其实用文件流也可以
size,count : integer; //文件大小
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
nmg_blnServerReady:boolean;
implementation
{$R *.dfm}
procedure TForm1.nmg_objClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := 'Connected to '+Socket.RemoteAddress;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
nmg_objClientSocket.Address := Edit1.Text;
//nmg_objClientSocket.Port:=2000;
nmg_objClientSocket.open;
end;
procedure TForm1.nmg_objClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
rcvtxt : string;
buf : array [1..2048] of char;
left : integer;
begin
rcvtxt := Socket.ReceiveText;
left := size - count; //未读字节数
if AnsiPos('go',rcvtxt)=1 then //收到响应则发
begin
StatusBar1.SimpleText := '正在传文件。'+Format('%3.0f',[count/size * 100]);
if sizeof(buf)<left then //若满一块则读一块
begin
stream.Read(buf,sizeof(buf));
Socket.SendBuf(buf,sizeof(buf));
count := count + sizeof(buf);
end
else //不满则发剩余的
begin
stream.Read(buf,left);
Socket.SendBuf(buf,left);
socket.Close;
end;
end;
if AnsiPos('yesReady',rcvtxt)=1 then //收到响应则发
begin
stream := TMemoryStream.Create;
//if OpenDialog1.Execute then
//begin
stream.LoadFromFile('I:/a.exe');
size := stream.Size; //获得文件大小
StatusBar1.SimpleText := '准备传文件。文件大小:'+inttostr(size);
count := 0;
//nmg_objClientSocket.Socket.SendText(); //先发送大小
Socket.SendText(inttostr(size));
//end;
end;
if AnsiPos('noReady',rcvtxt)=1 then //收到响应则发
begin
showmessage('noready');
nmg_blnServerReady := false;
Socket.Close;
end;
end;
procedure TForm1.nmg_objClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := 'disconnect';
end;
end.
服务器端:
unit server3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, ComCtrls, StdCtrls;
type
TdealThread = class(TServerClientThread)
private
protected
procedure ClientExecute; override;
public
thr:tserverclientwinsocket;
end;
type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
StatusBar1: TStatusBar;
SaveDialog1: TSaveDialog;
nmg_txtMonitorDir: TEdit;
procedure FormCreate(Sender: TObject);
procedure ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
private
{ Private declarations }
Tof : file;
size,count :integer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
//ServerSocket1.Port := 2000;
ServerSocket1.Active := true;
StatusBar1.SimpleText := 'Listening...';
end;
procedure TForm1.ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := 'Connected from '+ Socket.RemoteAddress;
if nmg_txtMonitorDir.Text = '' then
Socket.SendText('noReady')
else
Socket.SendText('yesReady');
end;
procedure TForm1.ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread);
var
myt:tdealthread;
begin
myt:=tdealthread.Create(false,clientsocket) ;//这个
myt.thr :=clientsocket;
socketthread:=myt;
end;
procedure TdealThread.ClientExecute;
var
Stream : TWinSocketStream;
Buf : array[1 .. 2048] of Char;
senddata:ansistring;
revData,fileName:string;
left,len : integer;
begin
{ make sure connection is active }
while (not Terminated) and ClientSocket.Connected do
begin
try
Stream := TWinSocketStream.Create(ClientSocket, 60000);
try
FillChar(Buf, SizeOf(Buf), 0); { initialize the buffer }
{ give the client 60 seconds to start writing }
if Stream.WaitForData(60000) then
begin
if Stream.Read(Buf, SizeOf(Buf)) = 0 then { if can't read in 60 seconds }
ClientSocket.Close; { close the connection }
len := Stream.Size;
//if len = 1 then
if len < 10 then
begin
Stream.Read(Buf, SizeOf(Buf));
Repeat
fileName := 'c:/temp/'+IntToStr(Random(10000))+'.exe';
Until not FileExists(fileName);
AssignFile(Form1.ToF, fileName);
Rewrite(Form1.ToF, 1);
ClientSocket.SendText('go');
end
else
begin
left := Form1.size - Form1.count; //未写的字节数
if sizeof(buf)<left then //满一块则写一块
begin
Stream.Read(Buf, SizeOf(Buf));
BlockWrite(Form1.Tof,buf,sizeof(buf));
Form1.count := Form1.count + sizeof(buf);
ClientSocket.SendText('go');
end
else //否则写剩余字节数
begin
Stream.Read(Buf, SizeOf(Buf));
BlockWrite(Form1.Tof,buf,left);
CloseFile(Form1.Tof);
ClientSocket.Close;
end;
end;
end
else
ClientSocket.Close; { if client doesn't start, close }
finally
Stream.Free;
end;
except
HandleException;
end;
end;
end;
end.
我的代码问题出在哪?