一传比较大的文件,比如5M以上的,就会发生数据接收不全,这是怎么回事服务端procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  C : PCON;
  cmd:String;
  Buffer : pointer;
  nRetr : integer;
  ReadCount : integer;
const
  bufferSize = 1024 ;
begin
C:= Socket.Data ;
case c.Status of
0 :
begin
cmd := trim(Socket.ReceiveText) ;if Pos('UPLOAD ',uppercase(cmd)) > 0 then
begin
  c.FileName := trim(Copy(cmd,Pos(' ',cmd)+1,Length(cmd)));
  c.TotalSize := StrToInt(Copy(c.FileName,Pos(' ',c.FileName)+1,Length(c.FileName)));
  c.FileName := trim(Copy(c.FileName,1,Pos(' ',c.FileName)));
  c.Status := 1;
  Socket.Data := C;
  fs :=TFileStream.Create('data\'+c.FileName,fmCreate or fmShareDenyNone);
  fs.Free;
//  fs.Seek(0,soFromBeginning);
  Socket.SendText('SEND');
end;
end;
1 : begin
  inc(i);
  GetMem(Buffer,BufferSize);
  nRetr := Socket.ReceiveBuf(Buffer^,BufferSize);
  if FIleExists('data\'+c.FileName) then
  begin
      fs :=TFileStream.Create('data\'+c.FileName,fmOpenWrite or fmShareDenyNone);
      fs.Seek(0,soFromEnd);
  end;  fs.WriteBuffer(Buffer^,nRetr);
//  fs.Destroy;
  FreeMem(Buffer);
end;
end;end;
客户端
procedure TForm2.CSRead(Sender: TObject; Socket: TCustomWinSocket);
var
  rlt : String;
  fs : TFileStream;
  Buf : pointer;
  nRead : Integer;
  m_bSending : boolean;
  lBytesSent : longint;
  i:integer;
begin
  rlt := Socket.ReceiveText;
  i:=0;
  if rlt='SEND' then
  begin
  lBytesSent:=0;
  m_bSending := TRUE;
  fs := TFileStream.Create(c.FileName,fmOpenRead or fmShareDenyNone);
  GetMem(Buf,fs.Size);
  while m_bSending do
  begin
    inc(i);
    if (fs.Seek(lBytesSent,soFromBeginning) = lBytesSent) then
    begin
      nRead := fs.Read(Buf^,1024);
      try
        Form2.ProgressBar1.Position := fs.Position;
        Cs.Socket.SendBuf(Buf^,nRead);
      except
      end;
      if nRead < 1024 then
      begin
        lBytesSent := lBytesSent + nRead;
        m_bSending := false;
      end
      else
      begin
//  Sleep(2);
lBytesSent := lBytesSent + 1024;
      end;
    end
    else
      m_bSending := false;
  end;//endwhile
  end;//endif
  fs.Destroy;
  FreeMem(Buf);
  showMessage(inttostr(i));
end;

解决方案 »

  1.   

    没用socket传过这么大的文件,不过用Indy采用FTP方式来传送很简单的
      

  2.   

    if nRead < 1024 then
    我不知道你的nread有没有可能小于1024,因为你每次都读1024长。
    你可以自己分解每个包的长度,这样可以计算包的数量,每发送一个包,服务器端发回一个确认信息,这样才能够比较准确。
    每发送一个包后,必须加上一定的延时,否则在internet传输时肯定丢数据。
    服务器端缺少一个文件完整接收后复原的操作。
    从结构上看除了以上问题看不出其它问题,不过你的data并不是传送文件的好方式,不要照套别人的代码。
      

  3.   

    你有没有好的方法,能麻烦发一份给我吗?
    [email protected]
      

  4.   

    传输家延时,把BUFFER设的大点,BUFFER越小,传输次数越多,越容易丢数据
      

  5.   

    如果有更好的例子请也发一份给我,谢谢
    [email protected]
      

  6.   

    赫赫!因为socket不支持一次传这么大的文件,你必须把文件切割来传,我就是做了一个动态切割,每次最多传3m,传一个560m的电影文件用了25分钟,没问题!其实socket传文件也很稳定!而且速度不慢!
      

  7.   

    如果有更好的例子请也发一份给我,谢谢
    [email protected]
      

  8.   

    //传送过30M的文件,测试通过
    //客户端
    unit client;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ComCtrls, ScktComp;type
      TForm1 = class(TForm)
        ClientSocket1: TClientSocket;
        OpenDialog1: TOpenDialog;
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        Memo1: TMemo;
        ProgressBar2: TProgressBar;
        Edit1: TEdit;
        Edit2: TEdit;
        Edit3: TEdit;
        procedure Button2Click(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure ClientSocket1Connecting(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
        function  getfilename(str1:string):string;
      private
        { Private declarations }
      public
        { Public declarations }
      end;  type
      FileInf=Record
        name: String;         //文件名
        Size: Integer;        //文件大小
        sfile: TFileStream;   //文件
      end;
    var
      Form1: TForm1;
      mem: fileinf;
      posi, len: Integer;
    implementation{$R *.DFM}procedure TForm1.Button3Click(Sender: TObject);
    begin
      if ClientSocket1.Active then
        ClientSocket1.Active:=false;
      application.Terminate;
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      if ClientSocket1.active then clientsocket1.Active:=false;
      ClientSocket1.Host:= edit1.Text;
      ClientSocket1.Port:= StrToInt(edit2.Text);
      clientsocket1.active:=true;
    //    ClientSocket1.Active:=false;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if Opendialog1.Execute then
      begin
        edit3.Text:= Opendialog1.FileName;
        mem.name:= getfilename(Opendialog1.FileName);
      end;
    end;procedure TForm1.ClientSocket1Connecting(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
          Memo1.lines.Add('C: 正在链接...');
    end;procedure TForm1.ClientSocket1Read(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      p: Array[0..1023] of byte;
      RecStr: String;
    begin
      RecStr:= ClientSocket1.Socket.ReceiveText;
    //  Memo1.Lines.Add('S: '+RecStr);
      if Pos('连接成功', RecStr)> 0 then
      begin
        Memo1.Lines.Add('连接成功');
        Memo1.Lines.Add('C: 提交文件名');
        ClientSocket1.Socket.SendText('提交文件名: '+mem.name);
      end;  if Pos('成功收到文件名', RecStr)> 0 then
      begin
         posi:=0;
         len:=0;
         Try
           mem.sfile:= TFileStream.Create(mem.name, fmOpenRead);
           mem.Size:= mem.sfile.Size;
           Posi:= 0;
           Memo1.Lines.Add('C: 提交文件大小');
           ClientSocket1.Socket.SendText('提交文件大小: '+IntToStr(mem.size));
         finally
    //       mem.sfile.Free;
         end;
      end;//end if  if Pos('成功收到文件大小', RecStr)> 0 then
      begin
        Memo1.Lines.Add('C: 开始发送文件');
        ClientSocket1.Socket.SendText('开始发送文件');
      end;  if (Pos('可以发送', RecStr)> 0) or (Pos('继续发送', RecStr)> 0) then
      begin
        try
        //recfile:= TFileStream.Create(mem.name, fmOpenRead);
        if  Posi< mem.Size then
        begin
          len:= 1024;
          if mem.Size-posi< 1024 then len:= mem.Size-posi;
          mem.sfile.Position:=posi;
          mem.sfile.ReadBuffer(p,len);
    //      mem.sfile.read(p,len);
          ClientSocket1.Socket.SendBuf(p,len);
    //      memo1.lines.add('当前位置:'+inttostr(posi)+',长度:'+inttostr(len));
          if ProgressBar2.Position<>Round(posi/mem.Size*100) then
          Application.ProcessMessages;
          ProgressBar2.Position:= Round(posi/mem.Size*100);
          inc(posi, len);
        end;
        finally
        //mem.sfile.Free;
        //mem.sfile:=nil;
        end;
      end;  if Pos('文件接收失败', RecStr)> 0 then
      begin
        Memo1.Lines.Add('C: 重新提交文件名');
        ClientSocket1.Socket.SendText('提交文件名: '+mem.name);
      end;  if Pos('成功接收文件', RecStr)> 0 then
      begin
          mem.sfile.Free;
          mem.sfile:=nil;
          Memo1.Lines.Add('C: 发送文件结束');
          ClientSocket1.Socket.SendText('发送文件结束');
      end;
    end;function  TForm1.getfilename(str1:string):string;
    var
      myi:integer;
      str2:string;
    begin
      str2:='';
      if length(str1)=0 then result:=''
      else
      begin
        if pos('\',str1)<1 then result:=str1
        else
        begin
          for myi:=length(str1) downto 1 do
          begin
            if str1[myi]='\' then  Break;
            str2:=str1[myi]+str2;
          end;
          result:=str2;
        end;
      end;
    end;end.
      

  9.   


    //服务端
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ComCtrls, StdCtrls, ScktComp;type
      TForm1 = class(TForm)
        ServerSocket1: TServerSocket;
        Memo1: TMemo;
        Button1: TButton;
        Button2: TButton;
        ProgressBar1: TProgressBar;
        Button3: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure ServerSocket1ClientConnect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ServerSocket1ClientRead(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ServerSocket1ClientDisconnect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ServerSocket1ClientError(Sender: TObject;
          Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
          var ErrorCode: Integer);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      Sendf: boolean;
      filename:String;
      filesize:integer;
      recfile: TFileStream;
      ReadCount : integer;
    implementation{$R *.DFM}procedure TForm1.Button1Click(Sender: TObject);
    begin
      if Button1.Caption = 'Active' then
      begin
        Button1.Caption := 'Stop';
        ServerSocket1.Active := true;
      end
      else begin
        Button1.Caption := 'Active';
        ServerSocket1.Active := false;
      end;
    sendf:=false;  
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin  if ServerSocket1.Active then
        ServerSocket1.Active:= False;
      application.Terminate;  
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
    button1Click(self);end;procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
    socket.SendText('连接成功...');end;procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      recStr: String;
      Buffer : pointer;
      nRetr : integer;
    const
      bufferSize = 1024 ;begin
      if not sendf then
      begin
      RecStr:= socket.ReceiveText;
      memo1.Lines.add(recstr);
      end;
      if Pos('提交文件名', RecStr)>0 then
      begin
        delete(RecStr, 1, length('提交文件名: '));
        filename:='.\data\'+RecStr;
        socket.SendText('成功收到文件名');
      end;  if Pos('提交文件大小', RecStr)>0 then
      begin
        delete(RecStr, 1, length('提交文件大小: '));
        fileSize:=StrToIntDef(RecStr,0);
        if FileExists(Filename) then Deletefile(filename);
        recfile :=TFileStream.Create(filename,fmCreate or fmShareDenyNone);
    {    if recfile<>nil then
        begin
          recfile.Free;
          recfile:= nil;
        end;}
        socket.SendText('成功收到文件大小');
      end;  if sendf then
      begin
        GetMem(Buffer,BufferSize);
        nRetr := Socket.ReceiveBuf(Buffer^,BufferSize);
        inc(readcount, nretr);
        ProgressBar1.Position:= Round(readcount/filesize*100);
        Application.ProcessMessages;    {if FIleExists(filename) then
        begin
          recfile :=TFileStream.Create(filename,fmOpenWrite or fmShareDenyNone);
          recfile.Seek(0,soFromEnd);
        end;}
        recfile.write(Buffer^,nRetr);
        FreeMem(Buffer);
        //recfile.Free;
        //recfile:= nil;    if readcount=filesize then
        begin
         memo1.Lines.add('成功接收文件');
         socket.SendText('成功接收文件');
         recfile.Free;
         recfile:=nil;
         sendf:=false;
        end
        else socket.SendText('继续发送');
      end;  if Pos('开始发送文件', RecStr)>0 then
      begin
         socket.SendText('可以发送');
         ReadCount:=0;
         sendf:=true;
      end;
    end;procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
    showmessage('客户已停止链接');
    end;procedure TForm1.ServerSocket1ClientError(Sender: TObject;
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
      var ErrorCode: Integer);
    begin
    showmessage('客户已出错');
    end;end.
      

  10.   

    谢谢stbrine(brine),我把你的代码拿去试试看!