delphi TServerSocket与TClientSocket传送文件 Client发送一次文件server的read事件被触发了几千次

老子横刀向天笑 2013-11-03 12:26:35
如题,Client发送一次文件server的read事件被触发了几千次,很蛋疼,哎,不知道怎么回事,怎么找都找不出问题所在,client客户端发数据是一次性全部发出去的(并没有分批发送),服务端read事件为什么会被触发那么多次,最后导致文件不停地被覆盖,接收下来的文件有时几十kb有时0kb,不知道大家遇到过这种情况没有,大家帮我看看,

客户端发送数据:

procedure TForm1.Button1Click(Sender: TObject);
begin
if(OpenDialog1.Execute)then
begin
SendFileOnetime(OpenDialog1.FileName);
end;
end;

procedure TForm1.SendFileOnetime(FileName: string); //一次性发送文件
var trans:file of Byte;
FileLen:Integer;
Blockbuff:pointer;
socket:TCustomWinSocket;
begin
if(isServer) then socket:=ServerSocket1.Socket else socket:=ClientSocket1.Socket;
AssignFile(trans,filename);
Reset(trans);
FileLen:=FileSize(trans);
GetMem(Blockbuff,FileLen);
BlockRead(Trans,Blockbuff^,FileLen);
socket.SendBuf(Blockbuff^,FileLen);

FreeMem(Blockbuff);
end;

服务端接收数据:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; //服务端读取数据
Socket: TCustomWinSocket);
var recstr:string;
begin
ReceiveFile('c:\aa.mp3',Socket);
RecCount:=RecCount+1;
Label1.Caption:=IntToStr(RecCount);
end;

function TForm1.ReceiveFile(FileName: string;socket:TCustomWinSocket): Boolean; //接收文件
var
Trans:file of Byte;
Blockbuff:array[0..BlockLen-1] of Byte; //字节数组
FileLen:Integer; //字节总数
RemainLen:Integer; //剩余字节数
i:Integer;
ReceiveLen:Integer;
begin
AssignFile(Trans,FileName);
Rewrite(Trans);
FileLen:=FileSize(Trans);
ProgressBar1.Min:=0;
ProgressBar1.Max:=socket.ReceiveLength;
ReceiveLen:=socket.ReceiveBuf(Blockbuff,BlockLen);
ProgressBar1.Position:= ProgressBar1.Position+ReceiveLen;
if(ReceiveLen=BlockLen)then
begin
while(ReceiveLen>0)do
begin
i:=i+ReceiveLen;

BlockWrite(Trans,Blockbuff[0],ReceiveLen); //写数据
ReceiveLen:=socket.ReceiveBuf(Blockbuff,BlockLen); //继续接收
ProgressBar1.Position:= ProgressBar1.Position+ReceiveLen;
end;
end;
CloseFile(Trans);
//ShowMessage(Format('接收文件大小%d字节--%dMB',[i,((i div 1024) div 1024)]));
//ShowMessage('文件传输成功!');
end;


如图
(图片死上传不上来)
http://bbs.2ccc.com/attachments/2013/humingtao_2013113122830.png


所有的分数全部拿出来,麻烦大家帮我看看
...全文
209 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
wangyang4506 2013-11-04
  • 打赏
  • 举报
回复
引用 楼主 hutao1101175783 的回复:
如题,Client发送一次文件server的read事件被触发了几千次,很蛋疼,哎,不知道怎么回事,怎么找都找不出问题所在,client客户端发数据是一次性全部发出去的(并没有分批发送),服务端read事件为什么会被触发那么多次,最后导致文件不停地被覆盖,接收下来的文件有时几十kb有时0kb,不知道大家遇到过这种情况没有,大家帮我看看, 客户端发送数据:

procedure TForm1.Button1Click(Sender: TObject);
begin
  if(OpenDialog1.Execute)then
  begin
    SendFileOnetime(OpenDialog1.FileName);
  end;
end;

procedure TForm1.SendFileOnetime(FileName: string);  //一次性发送文件
var trans:file of Byte;
  FileLen:Integer;
  Blockbuff:pointer;
  socket:TCustomWinSocket;
begin
  if(isServer) then socket:=ServerSocket1.Socket else socket:=ClientSocket1.Socket;
  AssignFile(trans,filename);
  Reset(trans);
  FileLen:=FileSize(trans);
  GetMem(Blockbuff,FileLen);
  BlockRead(Trans,Blockbuff^,FileLen);
  socket.SendBuf(Blockbuff^,FileLen);

  FreeMem(Blockbuff);
end;

服务端接收数据:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;  //服务端读取数据
  Socket: TCustomWinSocket);
  var recstr:string;
begin
    ReceiveFile('c:\aa.mp3',Socket);
    RecCount:=RecCount+1;
    Label1.Caption:=IntToStr(RecCount);
  end;

function TForm1.ReceiveFile(FileName: string;socket:TCustomWinSocket): Boolean; //接收文件
var
  Trans:file of Byte;
  Blockbuff:array[0..BlockLen-1] of Byte;   //字节数组
  FileLen:Integer;                        //字节总数
  RemainLen:Integer;                      //剩余字节数
  i:Integer;
  ReceiveLen:Integer;
begin
  AssignFile(Trans,FileName);
  Rewrite(Trans);
  FileLen:=FileSize(Trans);
  ProgressBar1.Min:=0;
  ProgressBar1.Max:=socket.ReceiveLength;
  ReceiveLen:=socket.ReceiveBuf(Blockbuff,BlockLen);
  ProgressBar1.Position:= ProgressBar1.Position+ReceiveLen;
  if(ReceiveLen=BlockLen)then
  begin
    while(ReceiveLen>0)do
    begin
      i:=i+ReceiveLen;
      
      BlockWrite(Trans,Blockbuff[0],ReceiveLen);         //写数据
      ReceiveLen:=socket.ReceiveBuf(Blockbuff,BlockLen);  //继续接收
      ProgressBar1.Position:= ProgressBar1.Position+ReceiveLen;
    end;
  end;
  CloseFile(Trans);
  //ShowMessage(Format('接收文件大小%d字节--%dMB',[i,((i div 1024) div 1024)]));
  //ShowMessage('文件传输成功!');
end;
如图 (图片死上传不上来) http://bbs.2ccc.com/attachments/2013/humingtao_2013113122830.png 所有的分数全部拿出来,麻烦大家帮我看看
引用 1 楼 leonlxw520 的回复:
你这结贴。。
wangyang4506 2013-11-04
  • 打赏
  • 举报
回复
TCP默认放缓冲区好像是8K,8*1024个字节,最大一包发送大概是64K,65536个字节,你一下子发一个MP3文件,虽然看似一次性发送,但也会被系统分成N个数据包发出去,所以你的server端会被触发N多次,最后一次触发覆盖就是接收的最后包数据,应该是这样,所以需要自己封装一个分包接收的函数,全部接收完之后再拼接保存下来。
江湖被花采 2013-11-04
  • 打赏
  • 举报
回复

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧