我用下面语句老出错,这是为何呀?
var
  rbyte:array [1..4096] of rbyte;
begin      
  IdTCPClient1.Socket.ReadBytes(rbyte,4096);
  ...
end;
提示错误是:
[Error] mclient.pas(56): E2033 Types of actual and formal var parameters must be identical我试着:
type
   TBytes=array of byte;
var
   rbyte:TBytes;
begin
   setLength(rbyte,4096);
   IdTCPClient1.Socket.ReadBytes(rbyte,4096);
   ..
end;
还是报错,这是为何呀?我用的是delphi2005中带的indy10
还请大侠们指点!谢谢!

解决方案 »

  1.   

    var
      lcBytes: Integer;
    ...
    begin
    ...
      lcBytes:= 4096;
      IdTCPClient1.Socket.ReadBytes(rbyte, lcBytes);
    ...
    end;可能采用的引用传递,而不是值传递的原因!
      

  2.   

    TBytes:array[0..4095] of char;应该只到4095吧  
      

  3.   

    还是不对呀,二位大侠,我用的delphi2005+INDY10
      

  4.   

    IdTCPClient1.Socket.ReadBytes(@rbyte, 4096);
      

  5.   

    是类型不匹配,TBytes是Indy10自己定义的。
    如下:uses IdGlobalvar
       rbyte:TBytes;begin    IdTCPClient1.Socket.ReadBytes(rbyte, 4096);
      

  6.   

    to  gzmhero(hihihi)大侠:
       高手高手!是的,我将IdGlobal加上去,是没有再报错了!
    大侠,我还想请教您一个问题,我想做一个传送文件的程序,一个服务端,一个客户端,服务端发送文件,客户端接收文件,下面是一部分代码,不知这样写对不对,还请指点:
    服务器端:
    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    begin
        AContext.Connection.IOHandler.WriteLn('Connected succeed');
        AContext.Connection.IOHandler.WriteFile('e:\aa.rar');
    end;客户端:
    procedure TForm1.Button1Click(Sender: TObject);
    var
        pos,FileSize:integer;
        rbyte:Tbytes;
        sFile:TFileStream;
    begin
        Try
          IdTCPClient1.Connect;
        except
          showmessage('连接失败!');
          exit;
        end;
        ......
        pos:=4096;
        sFile:=TFileStream.Create('e:\bb.rar',fmCreate);
        While pos<Filesize do
        begin
          IdTCPClient1.Socket.ReadBytes(rbyte,pos);
          sFile.Write(rByte,4096);
          inc(pos,4096);
        end;
    end;
      

  7.   

    没用过2005以及indy10,不过看你的代码,逻辑可能不行。
    是连接到服务器,服务器就自动写一个文件到你的客户端。
    你的接收代码逻辑也有点问题,rar文件可能写得不对。
      While pos<Filesize do
        begin
          IdTCPClient1.Socket.ReadBytes(rbyte,pos);
          sFile.Write(rByte,4096);
          inc(pos,4096);
        end;
    最后一包如果小于4096,你仍然会写4096个字节到文件中,造成文件错误。你的客户端的读文件代码应该写在TcpClient的OnWork事件中。
    procedure TForm1.IdTCPClient1Work(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCount: Integer);
    begin
    ......    
    end;
      

  8.   

    大侠,现在有个这样的问题,在重复执行
    IdTCPClient1.Socket.ReadBytes(rbyte,4096);
    这条语句时,rbyte的所含的内容一直不变,readbytes取的内容一直是开始的4096字节的内容。
    它不会取后面的内容。这是怎么回事?还请指点!
      

  9.   

    放到ONWork事件里,ReadBytes(rbyte,AWorkCount)
      

  10.   

    是不是在server端直接用writefile()不行?
    我想利用流先将文件打开,再按4096字节进行读取,用server端的iohandler写入,但我不清楚server端iohandler用哪个方法进行写?
      

  11.   

    大侠,我将代码放到onwork事件中,不会执行呀。
    客户端
    procedure TForm1.Button1Click(Sender: TObject);
    var
        pos,FileSize:integer;
        rbyte:Tbytes;
        sFile:TFileStream;
    begin
        Try
          IdTCPClient1.Connect;
        except
          showmessage('连接失败!');
          exit;
        end;
    end;procedure TForm1.IdTCPClient1Work(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCount: Integer);
    var
        pos,FileSize:integer;
        rbyte:Tbytes;
        sFile:TFileStream;
    begin
        pos:=0;
        FileSize:=StrToInt(IdTCPClient1.IOHandler.ReadLn);
        Showmessage(inttostr(filesize));
        sFile:=TFileStream.Create('e:\bb.doc',fmCreate);
        While pos<Filesize do
        begin
          IdTCPClient1.IOHandler.ReadBytes(rbyte,AWorkCount);
          sFile.Write(rByte,4096);
          inc(pos,4096);
        end;
        FreeAndNil(sFile);
    end;服务器端:
    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var
        sFile:TFileStream;
    begin
        sFile:=TFileStream.Create('e:\aa.doc',FmopenRead);
        AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
        showmessage(intTostr(sFile.Size));
        FreeAndNil(sFile);
        AContext.Connection.IOHandler.WriteFile('e:\aa.doc');
    end;
      

  12.   

    用WriteFile应该可以,是你的读取的可能不对。
    或者用IOHandler.Write(....),也可以写入。
      

  13.   

    那为什么我上面的客户端代码我点击了button1后,就没有反应了,我跟踪调试了,发现onwork里面的代码没有执行。这是怎么回事呢?还请大侠指点!谢谢!
      

  14.   

    没用过Indy,刚刚研究了一下。把你的代码略改了一下,还是按照你最早的思路。
    客户端:
    procedure TForm1.Button1Click(Sender: TObject);
    var
        FileSize:integer;
        rbyte:Tbytes;
        sFile:TFileStream;
    begin
        Try
          IdTCPClient1.Connect;
        except
          showmessage('连接失败!');
          exit;
        end;
        ......
        FileSize:=StrToInt(IdTCPClient1.IOHandler.ReadLn);    
        sFile:=TFileStream.Create('e:\bb.rar',fmCreate);
        
        While FileSize>4096 do
        begin
            IdTCPClient1.Socket.ReadBytes(rbyte,4096);
            sFile.Write(rByte,4096);
            inc(iFileSize,-4096);
        end;
        IdTCPClient1.Socket.ReadBytes(rbyte,iFileSize);
        sFile.Write(rByte,iFileSize);
        sFile.Free;
    end;服务端:
    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var
        sFile:TFileStream;
    begin
        sFile:=TFileStream.Create('e:\aa.doc',FmopenRead);
        AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
    //    showmessage(intTostr(sFile.Size));
        FreeAndNil(sFile);
        AContext.Connection.IOHandler.WriteFile('e:\aa.doc');
    end;
      

  15.   

    大侠,十分感谢您的回答!
    但这样还是不行,这样只是解决了文件大小问题,但是文件的内容全部变了,并且我在跟踪rbyte这个变量时,发现它的内容在while循环里面一直都是开始4096字节的内容,没有变化。
    好像ReadBytes这个方法只读取了开始的4096个字节的内容,后面的内容没有读取,是否还要在readbytes方法后面还要加上缓冲区移动指针的方法?但这如何做呢?还请您指点一下!谢谢!
      

  16.   

    我的Indy10不能用,不过我用Indy9的
            IdTCPClient1.ReadBuffer(rbyte,4096);
    是没问题的。都能读出来。传输也正常。
      

  17.   

    Indy10还是不稳定的
    建议Indy9.0.18的好http://lysoft.7u7.net
      

  18.   

    rbyte:申请内存没?
    Setlength(rbyte,4096);?
      

  19.   

    但我最近装了delphi2005,它本身带了indy10,所以我只能用indy10了。并且在上面的代码中[服务器端]里面的showmessage如果不注释掉,则会执行多次,这是怎么回事呢?
      

  20.   

    我试了,用setlength申请和不申请都是一样的!并且我发现服务器端的onExecute里面的语句会重复执行
      

  21.   

    IdTCPServerExecute方法是IdTCPServer 的OnExecute事件响应过程。OnExecute事件在TIdPeerThread对象试图执行其Run方法时发生。OnExecute事件与通常的事件有所不同,其响应过程是在某个线程上下文中执行的,参数AThread就是调用它的线程。这一点很重要,它意味着可能有多个OnExecute事件响应过程被同时执行。在连接被断开或中断前,OnExecute事件响应过程会被反复执行。
    由于IdTCPServerExecute方法在某一线程上下文中执行,因此显示数据和添加事件记录都是将相应的方法传递给Synchronize调用来完成的。/////////////////////////找不到问题,既然读第一包是好的,后面也应该没问题。
    装个indy9吧,保证没问题。 我的D2005的Indy10用都不能用。
      

  22.   

    ReadBytes is a virtual procedure used to perform a read request for the IOHandler.
    VBuffer is the variable argument used to store values read from the data source for the IOHandler connection.AByteCount indicates the number of byte values expected for the read request. When AByteCount contains 0 (zero), no data is read from the data source for the IOHandler. when AByteCount contains -1, data is read from the data source until it is disconnected or the ReadTimeout value has elapsed.ReadBytes reads data from the IOHandler data source until the number of bytes in AByteCount has been accumulated in InputBuffer, or CheckForDisconnect interrupts the read request.On successful completion of the read request, values are extracted from InputBuffer into VBuffer.AAppend indicates that values extracted from the input buffer should be appended to existing data in VBuffer. When AAppend is False, any values in VBuffer are discarded during extraction of data from InputBuffer.这是indy10帮助文件对readbytes方法的解释,有些不大理解
      

  23.   

    你试一下文本文件, 然后用
            IdTCPClient1.IOHandler.ReadLn

            IdTCPClient1.IOHandler.ReadString()看看对不对。
      

  24.   

    大侠,我试着做了一个实验:
    aa.txt文件里面只有一个字符a
    我对客户端程序进行调试,发现在语句执行后
    IdTCPClient1.Socket.ReadBytes(rbyte,FileSize);
    rbyte内容是84,0,0,0.....
    前面对rbyte分配的内存空间。setlength(rbyte,4096)
    怎么第一个字符是84呢?应该是61呀,
    而执行完sFile.Write(rByte,iFileSize);后,我用Ultraedit打开这两个文件aa.txt,bb.txt
    用HEX查看,
    发现aa.txt显示内容为:61
        bb.txt显示内容为:F0真是晕倒!这是怎么回事?越来越糊涂了!
      

  25.   

    var
      rbyte:array [1..4096] of rbyte;
    begin      
      IdTCPClient1.Socket.ReadBytes(@rbyte[1],4096);
      ...
    end;
      

  26.   

    这样再试试。    bytes:Array[0..4096] of Byte;
        rbyte:Tbytes;
        sFile:TFileStream;
    begin
      rbyte:=@bytes[0];
    .....
      IdTCPClient1.Socket.ReadBytes(rbyte,4096);
    .....
      

  27.   

    奇怪,我按您说的方法用readln进行读取,出现的情况与上面一样,但bb.txt里面的内容十六进制显示为48,为字母H.
      

  28.   

    gzmhero(hihihi)和sephil(NAILY Soft)二位大侠,按您们所写的代码测试了一下,还是不行。:(
      

  29.   

    在执行这条语句时,
    IdTCPClient1.Socket.ReadBytes(rbyte,4096);
    rbyte的内容和 服务器端的内容就不对了!
      

  30.   

    你服务端启动,发送文本文件。
    用telnet测试,启动运行-》telnet
    >open>127.0.0.1 88888                          (ip和端口号)看看能不能看到服务端发送的文本文件。
      

  31.   

    gzmhero(hihihi) 大侠,我用telnet收到的信息是原文件aa.txt的内容a字符!
      

  32.   

    多试试。        
            IdTCPClient1.IOHandler.ReadString
            IdTCPClient1.IOHandler.ReadStream
    不是
            IdTCPClient1.Socket.ReadString
      

  33.   

    我试过IdTCPClient1.IOHandler.ReadStream,一执行到该语句,客户端就停在这里了,怎么点击都没有反应!在任务管理器显示客户端未响应!只有用任务管理器来终止客户端。
      

  34.   

    WriteFile calls write using a temporary TFileStream created for reading the contents of the file in AFile.WriteFile returns the number of bytes found in the file stream written to the IOHandler.服务器端writefile是将文件写入一个临时的文件流中。那是否是在客户端就要用readstream来读取这个流呢?但我执行IdTCPClient1.IOHandler.ReadStream或socket.readstream都会造成客户端程序死机。
    并且readstream方法是这样定义的:
    procedure ReadStream(AStream: TIdStreamVCL, AByteCount: LongInt = -1, AReadUntilDisconnect: Boolean = False); virtual;
    AByteCount和AReadUnitDisconnect可以省略。
    客户端我改成:
    procedure TForm1.Button1Click(Sender: TObject);
    var
        FileSize:integer;
        rbyte:Tbytes;
        sFile:TFileStream;
        bytes:array [0..4095] of byte;
        cFile:TIdStreamVCL;
    begin
        rbyte:=@bytes;
        Try
          IdTCPClient1.Connect
        except
          showmessage('连接失败!');
          exit;
        end;
        sFile:=TFileStream.Create('e:\bb.txt',fmCreate);
        cFile:=TIdStreamVCL.Create(sFile,true);
        IdTCPClient1.IOHandler.ReadStream(cFile);end;执行到IdTCPClient1.IOHandler.ReadStream(cFile);程序就不响应了,并且Delphi2005也不响应了。只有调了任务管理器将这二个程序终止,但服务器端还是正常运行!
      

  35.   

    TIdStreamVCL类中有一个VCLStream:TStream属性,我不清楚这个属性有没有用。
    我试着这样写:
    procedure TForm1.Button1Click(Sender: TObject);
    var
        FileSize:integer;
        rbyte:Tbytes;
        sFile:TFileStream;
        bytes:array [0..4095] of byte;
        cFile:TIdStreamVCL;
    begin
        rbyte:=@bytes;
        Try
          IdTCPClient1.Connect
        except
          showmessage('连接失败!');
          exit;
        end;
        FileSize:=StrToInt(IdTCPClient1.IOHandler.ReadLn);
        sFile:=TFileStream.Create('e:\bb.txt',fmCreate);
        cFile:=TIdStreamVCL.Create(sFile,true);
        While Filesize>4096 do
        begin
          cFile.VCLStream.Read(bytes,4096);
          inc(FileSize,-4096);
        end;
         cFile.VCLStream.Read(bytes,Filesize);
    end;程序运行没问题,但是bb.txt这个文件长度为0,什么内容都没有。
    而我用telnet看到服务端发送内容为a1,1是文件长度,a是文件内容
      

  36.   

    哈gzmhero(hihihi) 大侠,我好像试出一些眉目了,我等会将代码放上来,还请您和各位大侠再指点一下!
      

  37.   

    gzmhero(hihihi) 大侠,我将客户端程序改成如下:procedure TForm1.Button1Click(Sender: TObject);
    var
        FileSize:integer;
        rbyte:Tbytes;
        sFile:TFileStream;
        bytes:array [0..4095] of byte;
        cFile:TIdStreamVCL;
    begin
        Try
          IdTCPClient1.Connect
        except
          showmessage('连接失败!');
          exit;
        end;
        FileSize:=StrToInt(IdTCPClient1.IOHandler.ReadLn);
        sFile:=TFileStream.Create('e:\bb.txt',fmCreate);
        cFile:=TIdStreamVCL.Create(sFile);
        IdTCPClient1.IOHandler.InputBufferToStream(cFile,filesize);
    end;我开始测试时用的是一个1k大小文件,执行完后,文件接收正常,但我用大些文件,如63K,在执行时就会报:"Not enough data in buffer",这是怎么回事呢?
      

  38.   

    问题解决了。·#……%¥—%¥—**—*……%¥……%#%¥。服务端:
    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var
        sFile:TFileStream;
        sv:TIdStreamVCL;
    begin
        sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
        AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
        sv:=TIdStreamVCL.Create(sFile,true);
        AContext.Connection.IOHandler.Write(sv,sFile.Size);
        FreeAndNil(sFile);
    end;客户端:procedure TForm1.Button1Click(Sender: TObject);
    var
        FileSize:integer;
        sFile:TFileStream;
        sv:TIdStreamVCL;
    begin
        Try
          IdTCPClient1.Connect;
        except
          showmessage('连接失败!');
          exit;
        end;    FileSize:=StrToInt(IdTCPClient1.IOHandler.ReadLn);
        sFile:=TFileStream.Create('e:\bb.pas',fmCreate);
        sv:=TIdStreamVCL.Create(sFile,true);    While FileSize>4096 do
        begin
            IdTCPClient1.IOHandler.ReadStream(sv,4096);
            inc(FileSize,-4096);
        end;
        IdTCPClient1.IOHandler.ReadStream(sv,FileSize);
        sFile.Free;
    end;
      

  39.   

    gzmhero(hihihi) 大侠在吗?我发现inputbuffertostream()执行后,IdTCPClient1.IOHandler.InputBuffer.size的值为0怎么将服务器的数据放到buffer中呢?
      

  40.   

    gzmhero(hihihi)大侠,真的可以了!真是万分感谢您!再请您指点一下,在程序中为什么不利用socket呢?而IOHandler呢?
      

  41.   

    在传送过程中,主要是用TStreamVCL这个类来进行接收文件.
    大侠,再请问您一下,像上面的代码,当服务器端传送了文件大小后,是整数型,再接着传送文件,我用telnet来接收时,发现文件大小和文件内容重复传送,客户端在接收时是否是根据read的各种函数来接收服务器端发过来的数据?如:文件大小,客户端是用readln()来接收到,如果用readstream()来接收,那就会报错了。
    而文件内容是利用流来发送的,则客户端也要用readstream()函数来读取了.是这样理解吗?
      

  42.   

    用Socket好象也可以的吧。好象是的。
    对Indy的理解不是很深,不知道处理机制是怎么样的。