在局域网内用Socket传输文件的问题。。。。。。(急!)100分。。。 ( 积分: 100 )

  • 主题发起人 主题发起人 javesun
  • 开始时间 开始时间
J

javesun

Unregistered / Unconfirmed
GUEST, unregistred user!
最近做一个在局域网内用Socket传输文件的功能模块。。。。因水平差,调试了好几天了,都不行。。。网上也看了不少的资料。。。还是没有解决:现打代码发在这儿,请大虾给调试一下,看看是哪儿的问题:
客户端:
{
说明:用于客户端接收文件

1、首先和服务器建立通信。
2、在Edit3.Text里发送MP_Prepare信息,即发送需求并准备信息。在服务器接收后发送
  MP_Prepare信息,即做好准备。(具体见服务器单元)
 3、接收到 MP_Prepare信息,发送MP_Accept信息。服务器接收到 MP_Accept信息后,
发送MP_Data信息,即发送数据。
 4、接收到MP_Data信息后,接收数据。服务器端在发完后发送MP_Over信息,即发送完毕。
 5、接收到MP_Over信息后,保存文件,完毕。
 
 注:两端如有错误会发送MP_Error信息,另一端接收后终止传输文件。
}

unit Clientpas;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls, IdBaseComponent, IdComponent, Math,
IdTCPConnection, IdTCPClient;

type
TCilentFrm = class(TForm)
ClientSocket1: TClientSocket;
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
Edit3: TEdit;
Label3: TLabel;
Button2: TButton;
Button3: TButton;
Edit4: TEdit;
Label4: TLabel;
SaveDialog1: TSaveDialog;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
private
{ Private declarations }
PrvRecv: TFileStream;
public
{ Public declarations }
end;

var
CilentFrm: TCilentFrm;

implementation

{$R *.dfm}

Const
MP_Query = '1'; //发送需求
MP_Prepare = '2'; //做好准备
MP_Accept = '3'; //准备接收
MP_Data = '4'; //接收或发送数据
MP_Over = '5'; //完成
MP_Error = '6'; //发生错误
MP_Refuse = '7'; //拒绝

procedure TCilentFrm.Button1Click(Sender: TObject);
begin
if Button1.Caption= '连接' then
begin
ClientSocket1.Address:= Edit1.Text;
ClientSocket1.Port:= StrToInt(Edit2.Text);
ClientSocket1.Active:= True;
Button2.Enabled:= True;
Button1.Caption:= '断开';
Button3.Enabled:= True;
Memo1.Lines.Clear;
end
else
begin
ClientSocket1.Active:= False;
Button2.Enabled:= False;
Button1.Caption:= '连接';
Button3.Enabled:= False;
end;
end;

procedure TCilentFrm.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
// Button1.OnClick(Sender);

Button1.Caption:= '连接';
Button2.Enabled:= False;
Button3.Enabled:= False;
ShowMessage('Error!');
end;

procedure TCilentFrm.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Socket.SendText('Hello!');
end;

procedure TCilentFrm.ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ClientSocket1.Active:= False;
Button1.Caption:= '连接';
Button2.Enabled:= False;
Button3.Enabled:= False;
end;

procedure TCilentFrm.Button2Click(Sender: TObject);
begin
ClientSocket1.Socket.SendText(Edit3.Text); // Edit3.Text为 MP_Query时,即需求信息。
Edit3.Text:= '';
end;

procedure TCilentFrm.Button3Click(Sender: TObject);
var
MySaveName: String;
begin
MySaveName:= '校产备份.dat';
if SaveDialog1.Execute then
begin
Edit4.Text:= SaveDialog1.FileName;
PrvRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
PrvRecv.Position:= 0;
ClientSocket1.Socket.SendText(MP_Prepare); //发送准备完成信息
end
else
Edit4.Text:= '';
end;

procedure TCilentFrm.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
sTemp: String;
bufRecv: Pointer;
iRecvLength, i: integer;
begin
Memo1.Lines.Add( IntToStr(Memo1.Lines.Count)+ '* '); //+ Socket.ReceiveText);
sTemp:= Socket.ReceiveText;
case sTemp[1] of
MP_Prepare:
Socket.SendText(MP_Accept);
MP_Over:
begin
PrvRecv.Free;
Socket.SendText(MP_Over);
end
else
begin
try
GetMem(bufRecv, 5626); //2000 must >iBYTESEND //感觉问题出在这了。。。
Socket.ReceiveBuf(bufRecv^, iRecvLength); //测试过,接不到数据
PrvRecv.WriteBuffer(bufRecv^, i); //唉 !!!!!
finally
FreeMem(bufRecv);
end; //of try
Socket.SendText(MP_Accept);
end;
end;
end;

end.

服务器:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, WinSock, StdCtrls, IdBaseComponent, IdComponent,
IdTCPServer;

type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
Memo1: TMemo;
Button1: TButton;
Label1: TLabel;
LabHost: TLabel;
Label2: TLabel;
LabPort: TLabel;
Edit1: TEdit;
Button2: TButton;
OpenDialog1: TOpenDialog;
procedure ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
PrvSend: TFileStream;
public
{ Public declarations }
PubClientID: Integer;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

Const
MP_Query = '1'; //发送需求
MP_Prepare = '2'; //做好准备
MP_Accept = '3'; //准备接收
MP_Data = '4'; //接收或发送数据
MP_Over = '5'; //完成
MP_Error = '6'; //发生错误
MP_Refuse = '7'; //拒绝


procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.Add('SomeOne Login From:');
Memo1.Lines.Add('IP: '+ Socket.RemoteAddress);
Memo1.Lines.Add('Host: '+ Socket.RemoteHost);
PubClientID:= Socket.SocketHandle;
end;

procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.Add(Socket.RemoteAddress+ 'Disconnect');
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
sTemp: String;
bufSend: pointer;
iBYTEPERSEND: Integer;
ClientSocket: TCustomWinSocket;
begin
sTemp:= Socket.ReceiveText;
iBYTEPERSEND:= 5620;
ClientSocket:= TCustomWinSocket.Create(PubClientID);
Memo1.Lines.Add(IntToStr(Memo1.Lines.Count)+ '* '+ Socket.RemoteAddress+ ' send: '+ sTemp);
case sTemp[1] of
// MP_Query: Button2.Enabled:= True;
MP_Prepare: Button2.Enabled:= True;
MP_Accept:
begin
try
GetMem(bufSend,iBYTEPERSEND+1);
if (PrvSend.Position+1+iBYTEPERSEND) < PrvSend.Size then
begin
PrvSend.Read(bufSend^,iBYTEPERSEND);
ClientSocket.SendBuf(bufSend^,iBYTEPERSEND);
end//普通的发送,大小为iBYTEPERSEND
else
begin
PrvSend.Read(bufSend^,PrvSend.Size- PrvSend.Position-1);
ClientSocket.SendBuf(bufSend^,PrvSend.Size- PrvSend.Position-1);
PrvSend.Free;
ClientSocket.SendText(MP_Over);
end;//最后一次发送,发送剩余的数据
finally
FreeMem(bufSend,iBYTEPERSEND+1);
end;{of try}
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if Button1.Caption= '开始' then
begin
ServerSocket1.Active:= True;
Memo1.Clear;
Button1.Caption:= '停止';
LabHost.Caption:= ServerSocket1.Socket.LocalHost;
LabPort.Caption:= IntToStr(ServerSocket1.Port);
end
else
begin
ServerSocket1.Active:= False;
Button1.Caption:= '开始';
LabHost.Caption:= '';
LabPort.Caption:= '';
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
Socket: TCustomWinSocket;
begin
if OpenDialog1.Execute then
begin
Socket:= TCustomWinSocket.Create(PubClientID);
Edit1.Text:= OpenDialog1.FileName;
PrvSend:= TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
Socket.SendText(MP_Prepare);
end
else
Exit;
end;

end.

这里面有些Host等都是写在控制上的,没有在程序里写下来。。。

如有大虾好心写个,也可把代码发送到我的信箱:javesun@163.com。
 
最近做一个在局域网内用Socket传输文件的功能模块。。。。因水平差,调试了好几天了,都不行。。。网上也看了不少的资料。。。还是没有解决:现打代码发在这儿,请大虾给调试一下,看看是哪儿的问题:
客户端:
{
说明:用于客户端接收文件

1、首先和服务器建立通信。
2、在Edit3.Text里发送MP_Prepare信息,即发送需求并准备信息。在服务器接收后发送
  MP_Prepare信息,即做好准备。(具体见服务器单元)
 3、接收到 MP_Prepare信息,发送MP_Accept信息。服务器接收到 MP_Accept信息后,
发送MP_Data信息,即发送数据。
 4、接收到MP_Data信息后,接收数据。服务器端在发完后发送MP_Over信息,即发送完毕。
 5、接收到MP_Over信息后,保存文件,完毕。
 
 注:两端如有错误会发送MP_Error信息,另一端接收后终止传输文件。
}

unit Clientpas;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls, IdBaseComponent, IdComponent, Math,
IdTCPConnection, IdTCPClient;

type
TCilentFrm = class(TForm)
ClientSocket1: TClientSocket;
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
Edit3: TEdit;
Label3: TLabel;
Button2: TButton;
Button3: TButton;
Edit4: TEdit;
Label4: TLabel;
SaveDialog1: TSaveDialog;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
private
{ Private declarations }
PrvRecv: TFileStream;
public
{ Public declarations }
end;

var
CilentFrm: TCilentFrm;

implementation

{$R *.dfm}

Const
MP_Query = '1'; //发送需求
MP_Prepare = '2'; //做好准备
MP_Accept = '3'; //准备接收
MP_Data = '4'; //接收或发送数据
MP_Over = '5'; //完成
MP_Error = '6'; //发生错误
MP_Refuse = '7'; //拒绝

procedure TCilentFrm.Button1Click(Sender: TObject);
begin
if Button1.Caption= '连接' then
begin
ClientSocket1.Address:= Edit1.Text;
ClientSocket1.Port:= StrToInt(Edit2.Text);
ClientSocket1.Active:= True;
Button2.Enabled:= True;
Button1.Caption:= '断开';
Button3.Enabled:= True;
Memo1.Lines.Clear;
end
else
begin
ClientSocket1.Active:= False;
Button2.Enabled:= False;
Button1.Caption:= '连接';
Button3.Enabled:= False;
end;
end;

procedure TCilentFrm.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
// Button1.OnClick(Sender);

Button1.Caption:= '连接';
Button2.Enabled:= False;
Button3.Enabled:= False;
ShowMessage('Error!');
end;

procedure TCilentFrm.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Socket.SendText('Hello!');
end;

procedure TCilentFrm.ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ClientSocket1.Active:= False;
Button1.Caption:= '连接';
Button2.Enabled:= False;
Button3.Enabled:= False;
end;

procedure TCilentFrm.Button2Click(Sender: TObject);
begin
ClientSocket1.Socket.SendText(Edit3.Text); // Edit3.Text为 MP_Query时,即需求信息。
Edit3.Text:= '';
end;

procedure TCilentFrm.Button3Click(Sender: TObject);
var
MySaveName: String;
begin
MySaveName:= '校产备份.dat';
if SaveDialog1.Execute then
begin
Edit4.Text:= SaveDialog1.FileName;
PrvRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
PrvRecv.Position:= 0;
ClientSocket1.Socket.SendText(MP_Prepare); //发送准备完成信息
end
else
Edit4.Text:= '';
end;

procedure TCilentFrm.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
sTemp: String;
bufRecv: Pointer;
iRecvLength, i: integer;
begin
Memo1.Lines.Add( IntToStr(Memo1.Lines.Count)+ '* '); //+ Socket.ReceiveText);
sTemp:= Socket.ReceiveText;
case sTemp[1] of
MP_Prepare:
Socket.SendText(MP_Accept);
MP_Over:
begin
PrvRecv.Free;
Socket.SendText(MP_Over);
end
else
begin
try
GetMem(bufRecv, 5626); //2000 must >iBYTESEND //感觉问题出在这了。。。
Socket.ReceiveBuf(bufRecv^, iRecvLength); //测试过,接不到数据
PrvRecv.WriteBuffer(bufRecv^, i); //唉 !!!!!
finally
FreeMem(bufRecv);
end; //of try
Socket.SendText(MP_Accept);
end;
end;
end;

end.

服务器:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, WinSock, StdCtrls, IdBaseComponent, IdComponent,
IdTCPServer;

type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
Memo1: TMemo;
Button1: TButton;
Label1: TLabel;
LabHost: TLabel;
Label2: TLabel;
LabPort: TLabel;
Edit1: TEdit;
Button2: TButton;
OpenDialog1: TOpenDialog;
procedure ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
PrvSend: TFileStream;
public
{ Public declarations }
PubClientID: Integer;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

Const
MP_Query = '1'; //发送需求
MP_Prepare = '2'; //做好准备
MP_Accept = '3'; //准备接收
MP_Data = '4'; //接收或发送数据
MP_Over = '5'; //完成
MP_Error = '6'; //发生错误
MP_Refuse = '7'; //拒绝


procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.Add('SomeOne Login From:');
Memo1.Lines.Add('IP: '+ Socket.RemoteAddress);
Memo1.Lines.Add('Host: '+ Socket.RemoteHost);
PubClientID:= Socket.SocketHandle;
end;

procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.Add(Socket.RemoteAddress+ 'Disconnect');
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
sTemp: String;
bufSend: pointer;
iBYTEPERSEND: Integer;
ClientSocket: TCustomWinSocket;
begin
sTemp:= Socket.ReceiveText;
iBYTEPERSEND:= 5620;
ClientSocket:= TCustomWinSocket.Create(PubClientID);
Memo1.Lines.Add(IntToStr(Memo1.Lines.Count)+ '* '+ Socket.RemoteAddress+ ' send: '+ sTemp);
case sTemp[1] of
// MP_Query: Button2.Enabled:= True;
MP_Prepare: Button2.Enabled:= True;
MP_Accept:
begin
try
GetMem(bufSend,iBYTEPERSEND+1);
if (PrvSend.Position+1+iBYTEPERSEND) < PrvSend.Size then
begin
PrvSend.Read(bufSend^,iBYTEPERSEND);
ClientSocket.SendBuf(bufSend^,iBYTEPERSEND);
end//普通的发送,大小为iBYTEPERSEND
else
begin
PrvSend.Read(bufSend^,PrvSend.Size- PrvSend.Position-1);
ClientSocket.SendBuf(bufSend^,PrvSend.Size- PrvSend.Position-1);
PrvSend.Free;
ClientSocket.SendText(MP_Over);
end;//最后一次发送,发送剩余的数据
finally
FreeMem(bufSend,iBYTEPERSEND+1);
end;{of try}
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if Button1.Caption= '开始' then
begin
ServerSocket1.Active:= True;
Memo1.Clear;
Button1.Caption:= '停止';
LabHost.Caption:= ServerSocket1.Socket.LocalHost;
LabPort.Caption:= IntToStr(ServerSocket1.Port);
end
else
begin
ServerSocket1.Active:= False;
Button1.Caption:= '开始';
LabHost.Caption:= '';
LabPort.Caption:= '';
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
Socket: TCustomWinSocket;
begin
if OpenDialog1.Execute then
begin
Socket:= TCustomWinSocket.Create(PubClientID);
Edit1.Text:= OpenDialog1.FileName;
PrvSend:= TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
Socket.SendText(MP_Prepare);
end
else
Exit;
end;

end.

这里面有些Host等都是写在控制上的,没有在程序里写下来。。。

如有大虾好心写个,也可把代码发送到我的信箱:javesun@163.com。
 
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3254731
 
最好能用 TClientSocket/TServerSocket 控件。。。
 
我觉得直接拿现成的带Ftp功能的网络控件作就好了吧
 
要说完成类似的功能完全可以,但是用这个也能实现。
所以想请大虾指教一下,偶想多学习一下。。
呵呵。。。。。。。。
 
先站一个位置,等下回去再发给你!
 
receivetext把数据收走并清空了,能接收到数据就怪了.
 
to gekin;
怎么讲?
 
为什么用控件??
直接使用API就可以了呀!
比较简单的东东了!
 
给发个例子?javesun@163.com
谢谢!
 
前两天刚写了个上传下载的东东,服务器是多线程的,没那么复杂,CLIENT支持进度条,用起来还不错,性能也还可以,哈哈
 
能给我发一个吗?
 
高手来说说啊。。。
 
);
sTemp:= Socket.ReceiveText;
--------------------------
GetMem(bufRecv, 5626); //2000 must >iBYTESEND //感觉问题出在这了。。。
Socket.ReceiveBuf(bufRecv^, iRecvLength); //测试过,接不到数据
-----------------------------
PrvRecv.WriteBuffer(bufRecv^, i); //唉 !!!!!
 
gang18??
不明白啊。。。
 
在接收数据的时候receivetext 和receivebuf只能同时用一个
 
后退
顶部