传送端:
procedure Tf_Main.rb_upClick(Sender: TObject);
var
  nID:integer;
  nSize:Integer;
  n:Integer;
  p:pByte;
  data:TmemoryStream;
begin
data:=TmemoryStream.Create;
   try
      data.LoadFromFile(extractfilepath(application.EXEName)+'xfd.tmp');
      with ClientSocket1 do
      begin
           open;
           nSize:=data.Size;
           p:=data.Memory;
           while (nSize>0) do
           begin
                n:=nSize;
                if (n>8192) then
                    n:=8192;
                n:=Socket.SendBuf(p^,n);
                //
                if (n<=0) then
                  Raise Exception.Create('发送文件失败!');
                Inc(p,n);
                Dec(nSize,n);
           end;
           close;
      end;
   except on e:Exception do
            showmessage(e.Message);
   end;
    data.Free;
end;接收端:
procedure Tf_Server.ServerSocket1Accept(Sender: TObject;
  Socket: TCustomWinSocket);
var
  nID:integer;
  nSize:Integer;
  n:Integer;
  p:pByte;
  data:TmemoryStream;
begin
   data:=TmemoryStream.Create;
   GetMem(p,8192);
   try
      while (nSize>0) do
      begin
          n:=nSize;
          if (n>8192) then
              n:=8192;
          n:=Socket.ReceiveBuf(P^,n);
          if (n<=0) then
              Raise Exception.Create('');
          data.Write(p^,n);
          Dec(nSize,n);
      end;
      data.SaveToFile(extractfilepath(application.EXEName)+'xfd.tmp');
   except
   end;
   FreeMem(p);
   data.Free;
end;每次都是提示:发送文件失败!

解决方案 »

  1.   

    >>每次都是提示:发送文件失败!
                    n:=Socket.SendBuf(p^,n);
                    //
                    if (n<=0) then
                      Raise Exception.Create('发送文件失败!');
                    Inc(p,n);你的Socket是一个什么控件呀,,是否已经正确连接到你的ServerSocket呀,传输文件这样的功能,网络中有非常多的例子了,你可以参考一下1.在CSDN中查一下历史的帖子,FAQ
    2.到www.delphifans.com 有很多相关的代码的
      

  2.   

    我采用的TServerSocket/TClientSocket,其中TServerSocket的ServerType:=stThreadBlocking;
    TClientSocket的ClientType:=ctBlocking;ClientSocket能正确连接到ServerScoket如果在n:=Socket.SendBuf(p^,n);后加上showmessage(inttostr(n));需要每次点击对话框,最终是可以正常接收的我不知道问题出在哪儿,请各位大侠指点一下
      

  3.   

    p: pbyte;
    好象应该改成:p: ^DWORD;
      

  4.   

    1 client 部分我看不出什么问题, 出错的地方在 SendBuf 返回了 SOCKET_ERROR
    2 服务端部分就有点怪了, 放在 OnAccept 事件中去阻塞, OnAccept 有没在 TSocketClientThread 调度这个我记不得了, 改到 OnRead 中去试试看吧, 这个肯定是 TSocketClietnThread 调度执行的
      

  5.   

    晕, 认真看了服务端代码后发现
    var
      nID:integer;
      nSize:Integer;
      n:Integer;
      p:pByte;
      data:TmemoryStream;
    begin
       data:=TmemoryStream.Create;
       GetMem(p,8192);
       try
          while (nSize>0) do // 这句第一次执行时 nSize 是多少? 很想骂人了, 这个 while 根本一次就没执行就退出了, 后面发送的数据在 OnRead 事件中触发却没有任何的接收超时了
          begin           
              n:=nSize;      // 这里又是多少? 连个初值都没有
              if (n>8192) then // 这里 n 有可能比 8192 大?
                  n:=8192;
              n:=Socket.ReceiveBuf(P^,n);
              if (n<=0) then
                  Raise Exception.Create('');
              data.Write(p^,n);
              Dec(nSize,n);    
          end;
          data.SaveToFile(extractfilepath(application.EXEName)+'xfd.tmp');
       except
       end;
       FreeMem(p);
       data.Free;
    end;本质问题, 新鸟. 
    你没法在 TCP 的 socket 下知道后面的包大小, 至少你应该在发送数据前定义一个包头, 包头里面可以包括文件名, 目期, 关键的还是个文件尺寸, 像下面
    TFileHdr = packed record
      HdrSize: Integer;
      Name: array[0..80] of char;
      Date: TDateTime;
      Size: Integer;
    end;发送部分加上
      open; 后
      FileHdr.HdrSize := sizeof(TFileHdr);
      ...
      nSize:=data.Size;
      FileHdr.Size := nSize;
      Socket.SendBuf(FileHdr, SizeOf(FileHdr)); 
    这边强调一个事实就是, socket 不像是帮助中所说发送成功的长度是任何大小, 而有个最小成功大小, 因网不同而有 576-1460-3xxx 等不同数, 换名话说, 576 字节以下的一组数据是一定会发送成功, 因此像 TCP 的包头不因大于 576 字节, 嗯, 这是一个默认的少有文档会详细说事实. 但由于另一些特别原因
    1. 一般会把头 size 这个东东定义在结构的最头部, 为的是跟嵌入系统这类东东打交道时, 他们的资源很有限
    2. 把头后面会更的大小定义在头的最后部分懒得说了, 服务端
      

  6.   

    嗯, 为什么是 8192 一次发? 
    直接用 
    while nSize > 0 do 
      nSize - Socket.SendBuf(p^, nSize); 
    那个 8192 没有一种网络能一次到达, socket 一次能发送的大小是 MTU 决定的, 宽带就是 1460, modern 是 576
      

  7.   

    同意楼上的说法,建议LZ先去看看关于socket编程的基础知识。
      

  8.   

    不好意思各位大侠,不是我没有发送文件大小,是我复制代码时没复制全
               nSize:=data.Size;
               if (socket.SendBuf(nSize,SizeOf(nSize)) <> SizeOf(nSize)) then
                  Raise Exception.Create('发送文件大小错误!');
               p:=data.Memory;
    其实我的代码是按照delphi6高级编程中的例程输入的,我所迷惑的是:
    如果在n:=Socket.SendBuf(p^,n);后加上showmessage(inttostr(n));需要每次点击对话框,最终是可以正常接收的
      

  9.   

    谢谢comanche(太可怕)、wudi_1982(城里人真傻!) 的教诲,我是个菜鸟,还请各位大侠多多指点
      

  10.   

    如果用onclientread事件,那么一次发送2个以上的文件怎么接收阿?