Socket 文件传输

服务端

1.控件:TServerSocket

2.OnClientRead事件处理

procedure TMainForm.ssClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
msgr,theFileName:ansistring;
bufRecv:Pointer;
acc,iLength:Integer;
begin


acc:=0; //接收 0 1-不接受
//接收到的数据的长度
iLength:=Socket.ReceiveLength;
//开辟一块新的内存,用来保存接收到的数据
//GetMem(bufRecv,iLength+1);
  bufRecv:=AllocMem(iLength+1);     //// xe2 要AllocMem 且+1

{ //拷贝数据到缓存   d6
  Buf:=AllocMem(BufSize);

  StrCopy(Buf,pchar(st));
 }

try
//接收数据
Socket.ReceiveBuf(bufRecv^,iLength);
//将接收到的数据以字符串的形式存到msgr中
msgr:=StrPas(PansiChar(bufRecv));    //
//取前5个字符
msgr:=Copy(msgr,1,5);
if msgr=MP_QUERY then
begin
//去掉字符串前后的空格和控制字符
msgr:= StrPas(PansiChar(bufRecv));     //  PChar
//第5个字符后面的字符串为文件名
theFileName:=ExtractFileName(Copy(msgr,6,Length(msgr)-5));
 StB.Panels[0].Text:='准备接收文件';
memo1.Lines.Add('接收文件:'+theFileName);
//SaveDialog1.Title:='请选择或输入接收到的数据保存到的文件名:';
//SaveDialog1.FileName:=ansistring(theFileName);      //ansistring
//点击确认保存按钮
if acc=0 then //if SaveDialog1.Execute then
begin
//为需保存的文件创建文件流
 try
 fsRecv:=TFileStream.Create('V:\自助拷贝\内网到外网\'+theFileName,fmCreate);    //fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);

 except
  Socket.SendText(MP_ABORT);
  exit;
 end;
 //如果同意接收数据。
 StB.Panels[0].Text:='开始接收';
//memo1.Lines.Add ('开始接收!');
TickCount:=GetTickCount;
//发送同意接收文件的信息
Socket.SendText(MP_ACCEPT);
tStart:=False;
end
else
//发送拒绝接收文件的信息
Socket.SendText(MP_REFUSE);
end
else if msgr=MP_FILEPROPERTY then
begin
//接收文件长度并说明主机可以接收数据了
Socket.SendText(MP_NEXTWILLBEDATA);
end
else if msgr=MP_NEXTWILLBEDATA then
begin
//要求发送端发送数据
Socket.SendText(MP_DATA);
end else if msgr=MP_END then
begin
//memo1.Lines.Add ('文件:'+theFileName);
memo1.Lines.Add('成功');
StB.Panels[0].Text:= '传送完成';
//memo1.Lines.Add (timetostr(time())+'传送完成,接收耗时'+IntToStr(GetTickCount-TickCount)+'毫秒');
StB.Panels[1].Text:='接收耗时'+IntToStr(GetTickCount-TickCount)+'毫秒';
fsRecv.Free;
end
//接收到文件传送取消信息
else if msgr=MP_ABORT then
begin
//memo1.Lines.Add ('MP_ABORT');
StB.Panels[0].Text:= 'MP_ABORT';
Socket.SendText(MP_ABORT);
fsRecv.Free;
end
else
begin
if not tStart then
begin
//memo1.Lines.Add('接收文件...');
StB.Panels[0].Text:='接收文件...';
tStart:=True;
end;
//将接收缓冲区数据写入文件
fsRecv.WriteBuffer(bufRecv^,iLength);
//通知客户端继续发送数据
Socket.SendText(MP_DATA);
end;
finally
//释放内存
FreeMem(bufRecv,iLength);
end;
end;

 

客户端

1.控件TClienSockte

2.添加文件:

try
  StB.Panels.Items[0].Text:=('读文件');
  cs.Socket.SendText(MP_QUERY+ansistring(OpenDialog1.FileName));       //ansistring
   btnSendFile.Enabled:=false;
   Application.ProcessMessages;//增加简单多线程,防假死
except
  showmessage('无法连接服务器');
  btnSendFile.Enabled:=True;

end;

 

3. ClienSockte.open

4.TClienSockte onread 事件

//客户端接收来自服务器端的信息
procedure TForm1.csRead(Sender: TObject; Socket: TCustomWinSocket);
var
MsgRecv: ansistring; // ansistring
bufSend:pointer;
iLength:Integer;
begin
//得到客户端发来的信息
MsgRecv:=socket.ReceiveText;   //ansistring
//取前5位,得到协议标志符
MsgRecv:=copy(MsgRecv,1,5);
//接收到拒绝信息
if MsgRecv=MP_REFUSE then
StB.Panels.Items[0].Text:=('连接请求被拒绝!')
//接收到确认接收信息
else if MsgRecv=MP_ACCEPT then
begin
//为要发送的文件创建文件流
fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
tStart:=False;
//进度条显示
Probar.Max:=fsSend.Size;
StB.Panels.Items[0].Text:=('开始发送!');
memo1.Lines.Add('发送文件:'+OpenDialog1.FileName);
//获取发送开始时的时间
TickCount:=GetTickCount;
//创建文件流并发送文件长度。
Socket.SendText(MP_FILEPROPERTY+ ansistring(inttostr(Trunc(fsSend.Size/iBYTEPERSEND)+1)));
end
else if MsgRecv=MP_NEXTWILLBEDATA then
begin
//通知接收端将要传送数据。
Socket.SendText(MP_NEXTWILLBEDATA);
end
else if MsgRecv=MP_DATA then
begin
//接收到确认信息,开始发送数据。
if not tStart then
begin
StB.Panels.Items[0].Text:=('发送中...');
StB.Panels.Items[1].Text:=('');
Btnexit.Enabled:=false;
tStart:=True;
end;
//还有数据没有发送。
if fsSend.Position< fsSend.Size-1 then
begin
iLength:=fsSend.Size-1-fsSend.Position+1;
//将数据分段发送
if iLength>iBYTEPERSEND then
iLength:=iBYTEPERSEND;
GetMem(bufSend,iLength);
try
//读取文件流数据
fsSend.Read(bufSend^,iLength);
//发送长度为iLength的数据
Socket.SendBuf(bufSend^,iLength);
//进度条显示
Probar.Position:=fsSend.Position;
finally
//释放内存
FreeMem(bufSend,iLength);
end;
//发送完毕
end else
begin
//通知主机文件传送结束。
Socket.SendText(MP_END);

//获取发送耗时
memo1.Lines.Add('完成!');
StB.Panels.Items[0].Text:='发送完毕';
StB.Panels.Items[1].Text:='耗时'+IntToStr(GetTickCount-TickCount)+'毫秒' ;
btnSendFile.Enabled:=True;
Btnexit.Enabled:=True;
fsSend.Free;
end;
//取消文件发送过程
end else if MsgRecv=MP_ABORT then
begin
btnSendFile.Enabled:=True;
StB.Panels.Items[0].Text:=('文件传输被中止');
exit;
//文件传送取消
fsSend.Free;
end;
end;

posted @ 2015-01-30 15:44  realhopezj  阅读(346)  评论(0编辑  收藏  举报