怎么用程序模仿qq传文件!(100分)

  • 主题发起人 主题发起人 zixuexin
  • 开始时间 开始时间
Z

zixuexin

Unregistered / Unconfirmed
GUEST, unregistred user!
高手指教,我想做一个能够在局域网内传送文件的东东!能不能传一个文件夹呀!!
 
道理都是一样的,在自定义的协议里,用不同的协议标志识别传输的是文件还是文件夹名称。
如果传输的文件,则开始接收文件流,如果传输的文件夹,则建立对应的文件夹,在依次传输
文件夹里包含的文件。
 
可以用UDP啊! 或者 既然是局域网 装一个上传下载的软件不就得了 象 cuteftp
 
能不能给代码呀!
 
开始程序:
写一个最简单的,主要用于讲解方法。
定义协议:
Const
MP_QUERY ='1';
MP_REFUSE ='2';
MP_ACCEPT ='3';
MP_NEXTWILLBEDATA='4';
MP_DATA ='5';
MP_ABORT ='6';
MP_OVER ='7';
MP_CHAT ='8';

协议简介:
首先由Client发送MP_QUERY,Server接受到后发送MP_ACCEPT或MP_FEFUESE;
Client接受到MP_ACCEPT发送MP_FILEPROPERTY,Server接受到后发送MP_NEXTWILLBEDATA;
Client接受到发送MP_NEXTWILLBEDATA,Server接受到后发送MP_DATA;
Client接受到MP_DATA,发送数据,Server接受数据,并发送MP_NEXTWILLBEDATA;
循环,直到Client发送MP_OVER;
中间可以互相发送MP_CHAT+String;

Server程序:
放上以下控件:SaveDialog1,btnStartServer,
ss,(TServerSocket)

btnStartServer.OnClick(Sender:TObject);
begin
ss.Port:=2000;
ss.Open;
end;

ss.OnClientRead(Sender: TObject;Socket: TCustomWinSocket);
var
sTemp:string;
bufRecv:Pointer;
iRecvLength:integer;
begin
if bReadText then
begin
sTemp:=Socket.ReceiveText;
case sTemp[1] of
MP_QUERY:begin
//在这里拒绝
SaveDialog1.FileName:=Copy(sTemp,2,Length(STemp));
if SaveDialog1.Execute then
begin
Socket.SendText(MP_ACCEPT);
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
end
else Socket.SendText(MP_REFUSE+'去死');
end;
MP_FILEPROPERTY:begin
//要发送StrToInt(Copy(sTemp,2,Length(sTemp))) 次
//时间进度显示。。。
Socket.SendText(MP_NEXTWILLBEDATA);
end;
MP_NEXTWILLBEDATA:begin
Socket.SendText(MP_DATA);
bReadText:=false;
end;
MP_END:begin
fsRecv.Free
bReadText:=true;
end;
MP_ABORT:begin
fsRecv.Free;
bReadText:=true;
end;
MP_CHAT:begin
//Chat Msg
end;
end;{of case}
end
else begin
try
GetMem(bufRecv,2000);//2000 must >iBYTESEND
Socket.ReceiveBuf(bufRecv^,iRecvLength);
fsRecv.WriteBuffer(bufRecv^,iRecvLength);
finally
FreeMem(bufRecv,2000);
end;{of try}
bReadText:=true;
Socket.SendText(MP_NEXTWILLBEDATA);
end;
end;

Client程序:
放上以下控件:edtIPAddress,OpenDialog1,btnConnect,btnSendFile,
cs. (TClientSocket)

btnConnect.OnClick(Sender:TObject);
begin
cs.Address:=edtIPAddress.Text;
cs.Port:=2000;
cs.Connect;
end;

btnSendFile.OnClick(Sender:TObject);
begin
if OpenDialog1.Execute then
Begin
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);//FileSize???
 
end;
end;

cs.OnRead(Sender: TObject;Socket: TCustomWinSocket);
var
sTemp:string;
bufSend:pointer;
begin
sRecv:=Socket.ReceiveText;
Case sRecv[1] of
MP_REFUSE:ShowMessage('Faint,be refused!');
MP_ACCEPT:begin
fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpen);
//iBYTEPERSEND是个常量,每次发送包的大小。
Socket.SendText(MP_FILEPROPERTY+Trunc(fsSend.Size/iBYTEPERSEND)+1);
end;
MP_NEXTWILLBEDATA:begin
Socket.SendText(MP_NEXTWILLBEDATA);
end;
MP_DATA:begin
try
GetMem(bufSend,iBYTEPERSEND+1);
if (fsSend.Position+1+iBYTEPERSEND) < fsSend.Size then
begin
fsSend.Read(bufSend^,iBYTEPERSEND);
Socket.SendBuf(bufSend^,iBYTEPERSEND);
fsSend.Free;
end//普通的发送,大小为iBYTEPERSEND
else begin
fsSend.Read(bufSend^,fsSend.Size-fsSend.Position-1);
Socket.SendBuf(bufSend^,fsSend.Size-fsSend.Position-1);
end;//最后一次发送,发送剩余的数据
finally
FreeMem(bufSend,iBYTEPERSEND+1);
end;{of try}
end;
MP_ABORT:begin
//被取消了:(
fsSend.Free;
end;
end;{of case}
end;


整理程序:
  加入错误判断,优化程序,把Server和Client联合在一起,加入剩余时间进度显示,做成能一次传多个文件,加入聊天功能,就成了一个很好的点对点传文件的程序。


 
CopyFile函数是直接可以跨网络复制文件的(我只试过在同一个局与网里)
你可以先查找目录下所有文件,然后分别根据需要复制,
要想调用一个函数直接复制所有目录也行,用系统提供的
SHFileOperation 函数可以控制动化显示与否
function SysCopyFile(From, Destination: string): Boolean;
var
Sh: TSHFileOpStruct;
begin
with Sh do
begin
Wnd := Application.Handle;
wFunc := FO_COPY;
pFrom := PChar(From);
pTo := PChar(Destination);
lpszProgressTitle := '备份精灵——文件复制';
fFlags := 0;

fFlags := fFlags + FOF_ALLOWUNDO;
fFlags := fFlags + FOF_RENAMEONCOLLISION;
fFlags := fFlags + FOF_NOCONFIRMATION;
// fFlags := fFlags + FOF_SILENT;
end;
Result := SHFileOperation(Sh) = 0;
end;
 
那可不可以不经过对方同意直接发送呢?
 
完整qq传送程序,有显示文件大小,进度,发送者IP port等。//
unit Unitfile;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, Gauges, Buttons, StdCtrls, ExtCtrls, Psock, NMSTRM,
NMUDP;

type
Tfrmfile = class(TForm)
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
Panel1: TPanel;
Panel2: TPanel;
StatusBar: TStatusBar;
edt_name: TEdit;
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
StatusBar1: TStatusBar;
Edit1: TEdit;
SpeedButton3: TSpeedButton;
SpeedButton4: TSpeedButton;
NMStrm1: TNMStrm;
Panel3: TPanel;
filegress: TGauge;
Panel4: TPanel;
greceive: TGauge;
NMStrmServ1: TNMStrmServ;
procedure FormShow(Sender: TObject);
procedure NMStrm1ConnectionFailed(Sender: TObject);
procedure NMStrmServ1ClientContact(Sender: TObject);
procedure NMStrmServ1MSG(Sender: TComponent; const sFrom: String;
strm: TStream);
procedure SpeedButton1Click(Sender: TObject);
procedure NMStrm1PacketSent(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SpeedButton3Click(Sender: TObject);
private
{ Private declarations }
public
fileIP:String;
FromIP,RemoteComputerName:String;
HostIP:String;
fName:String;
procedure sendfile(Sender:TObject);
{ Public declarations }
end;

var
frmfile: Tfrmfile;

implementation

uses main;

{$R *.dfm}

procedure Tfrmfile.FormShow(Sender: TObject);
begin
StatusBar.Panels[0].Text:='IP:'+FromIP;
StatusBar.Panels[1].Text:='名称:'+RemoteComputerName;
SpeedButton1.Enabled:=True;
SpeedButton3.Enabled:=True;
end;

procedure Tfrmfile.NMStrm1ConnectionFailed(Sender: TObject);
begin
ShowMessage('Connection Failed');
end;

procedure Tfrmfile.NMStrmServ1ClientContact(Sender: TObject);
begin
NMStrmServ1.ReportLevel := Status_Basic;
NMStrmServ1.TimeOut := 90000;
StatusBar1.Panels[2].Text := 'Client connected';
end;

procedure Tfrmfile.NMStrmServ1MSG(Sender: TComponent; const sFrom: String;
strm: TStream);
var
MyFStream: TFileStream;
// MYFstream:TMemoryStream;
begin
// ShowMessage('receive');
// ShowMessage(fName);

// MyFStream := TMemoryStream.Create;

// if SaveDialog1.Execute then
// begin
MyFStream := TFileStream.Create(Edit1.Text, fmCreate);
try
MyFStream.CopyFrom(strm, strm.size);
// MyFStream.LoadFromStream(strm);
//MyFStream.SaveToFile(Edit1.Text);
finally
MYFStream.Free;
end;
//end;

end;

procedure Tfrmfile.SpeedButton1Click(Sender: TObject);
var
MyStream: TMemoryStream;
TmpStr: String;
SendFname:string;
Begin
SendFname:=ExtractFileName(edt_name.text);
//ShowMessage(SendfName);
MainForm.FUDP.ReportLevel := Status_Basic;
MainForm.FUDP.RemoteHost :=FromIP;
// MainForm.FUDP.RemoteHost :='job2125';
MainForm.FUDP.RemotePort :=7000;
TmpStr :='H_FILE'+SendFName;
MyStream := TMemoryStream.Create;
try
MyStream.Write(TmpStr[1], Length(TmpStr));
MainForm.FUDP.SendStream(MyStream);
finally
MyStream.Free;
end;
SpeedButton1.Enabled:=false;
end;
{var
MyFStream: TFileStream;
begin

NMStrm1.Host := FromIP;
NMStrm1.FromName :=RemoteComputerName;
MyFStream := TFileStream.Create(edt_name.Text, fmOpenRead);
try
NMStrm1.PostIt(MyFStream);
finally
MyFStream.Free;
end;
end;
}

procedure Tfrmfile.sendfile(Sender:TObject);
var
MyFStream: TFileStream;
begin
//ShowMessage('sendfunction');
// ShowMessage(FromIP);
NMStrm1.Host :=FromIP;
// NMStrm1.Host:='202.116.191.185';
//NMStrm1.FromName :=RemoteComputerName;
MyFStream := TFileStream.Create(edt_name.Text, fmOpenRead);
try
NMStrm1.PostIt(MyFStream);
finally
MyFStream.Free;
end;
end;
procedure Tfrmfile.NMStrm1PacketSent(Sender: TObject);
//begin
//filegress.Progress:= Round((100*NMStrm1.BytesSent/NMStrm1.BytesTotal));
var
MyStream: TMemoryStream;
TmpStr: String;
Begin
filegress.Progress:= Round((100*NMStrm1.BytesSent/NMStrm1.BytesTotal));
MainForm.FUDP.ReportLevel := Status_Basic;
MainForm.FUDP.RemoteHost :=FromIP;
MainForm.FUDP.RemotePort :=7000;
TmpStr :='F_BYTE'+IntToStr(filegress.progress);
MyStream := TMemoryStream.Create;
try
MyStream.Write(TmpStr[1], Length(TmpStr));
MainForm.FUDP.SendStream(MyStream);
finally
MyStream.Free;
end;

end;

procedure Tfrmfile.SpeedButton2Click(Sender: TObject);
begin
Close;
//sendfile(Sender);
end;

procedure Tfrmfile.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//Action:=caFree;
end;

procedure Tfrmfile.SpeedButton3Click(Sender: TObject);
var
MyStream: TMemoryStream;
TmpStr: String;
IPFrm:String;
Begin
// ShowMessage(Copy(Statusbar1.Panels[0].text,4,length(StatusBar1.Panels[0].text)));
IPFrm:=Copy(Statusbar1.Panels[0].text,4,length(StatusBar1.Panels[0].text));
MainForm.FUDP.ReportLevel := Status_Basic;
//ShowMessage(IPFrm);
//MainForm.FUDP.RemoteHost := IPFrm;
//MainForm.FUDP.RemoteHost :=Copy(Statusbar1.Panels[0].text,4,length(StatusBar1.Panels[0].text));
MainForm.FUDP.RemoteHost:=fileIP;
ShowMessage(MainForm.FUDP.RemoteHost);
//MainForm.FUDP.RemoteHost:='202.116.191.185';

// MainForm.FUDP.RemotePort :=7000;
TmpStr :='OK_FILE';
MyStream := TMemoryStream.Create;
try
MyStream.Write(TmpStr[1], Length(TmpStr));
MainForm.FUDP.SendStream(MyStream);
finally
MyStream.Free;
end;
SpeedButton3.Enabled:=false;

end;

end.
 
楼上的,你MAINFORM单元的源代码呢?
 
已经很详细了
 
后退
顶部