如果我想服务器可以同时连入多个客户端,那服务器端这个多线程该如何编写呢?我不知道如何从IdTCPServer这个控件下手,还请指点,谢谢!

解决方案 »

  1.   

    不用多线程,IdTcpServer自己会处理,你只要在相应的事件里写就行了。
    OnConnect,OnExecute.procedure TForm1.Button1Click(Sender: TObject);
    begin
        IdTCPServer1.Active:=true;
    end;procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
    begin
        Memo1.Lines.Add('connect');
    end;procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
    var
        sFile:TFileStream;
    begin
        sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
        AThread.Connection.WriteLn(IntToStr(sFile.Size));
        FreeAndNil(sFile);
        AThread.Connection.WriteFile('e:\fmLogin.pas');  
    end;
      

  2.   

    IdTcpServer的每个连接是一个TIdPeerThread,放在列表Threads: TThreadList;中,   pt:TIdPeerThread pt:=idTcpServer.Threads.LockList.Items[i];
    pt.Connection.WriteBuffer(...);
      

  3.   

    大侠,在indy10里面IdTCPserver1Execute是这种格式:
    IdTCPServer1Execute(AContext: TIdContext);
    我没有找到和Thread有关的属性
      

  4.   

    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var
        sFile:TFileStream;
    begin
        sFile:=TFileStream.Create('e:\aa.doc',FmopenRead);
        AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
        FreeAndNil(sFile);
        AContext.Connection.IOHandler.WriteFile('e:\aa.doc');
    end;
      

  5.   

    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;
      

  6.   

    本身一个IdTcpServer就可以多个Client连接的,不要你写什么多线程的。
      

  7.   

    最近都混在socket这块,常听gzmhero大侠讲解受益甚深啊~~
    gzmhero,谢谢!!!鞠躬
      

  8.   

    indy10还没有体验过,不知道从哪里下载,装上之后会不会覆盖d7自带的版本?
      

  9.   

    cjf1009(农民程序员) ///////////////////////////
    不会覆盖,形成不同的bpl,你可以选择使用indy9或者indy10。
      

  10.   

    gzmhero(hihihi)大侠,有个这样问题,不知您是否能指点一下:
    我想先将数据备份了,再进行传送,我在服务器端设置了一个自动备份的时间,IdTCPServer是一启动程序时我就将其设置Actived;在客户端设置了接收时间,当时间一到,则客户端启动IdTCPClient.Connect,但我发现备份时间过长了,超过了客户端设置的接收时间,就会造成客户端接收数据不正确!但如果是将服务器端的备份时间设置的比客户端的接收时间提前,那是可以,但是我不能掌握备份时间要多久,所以我觉得这样还是不行。如果我在备份后才启动IdTCPServer,但客户端的接收时间就不能确定了,这样我觉得也不行!我现在是这样做的:在服务器onexecute这个事件中设置了一个循环,并加了一个变量用来判断是否备份完成,如果备份完成就发送‘OK’字符串到客户端,并且在这个循环里不停的发送‘NO’到客户端;同样,在客户端我也设置了一个循环,在循环里面不停的接收服务器端发过来的字符并进行判断,如果是OK则退出循环,进入传送数据状态,反之,继续接收。但这样有时还是会出些问题。我想做到备份数据完后,客户端才开始接收数据,但备份时间不能确定有多久。
    对上面这个问题,不知是否还有其他的解决办法?不知您是否能指点一下?谢谢!
      

  11.   

    这样的逻辑看看行不行:
    服务端:
    1、IdTcpServer打开。
    2、备份数据。
    3、备份完成后,对连接的客户端发送命令,自己定义.譬如'Ready'
    4、发送文件。客户端:
    1、在一个线程里循环。
       1)连接服务端。
       2)读服务端数据,循环读,直到读到Ready
    2、接收文件。
      

  12.   

    对,放到线程里,在读到Ready后。
      

  13.   

    如果当时客户端不在线呢?不是错过了更新的机会?
    我觉得这类似于升级程序,得客户端主动,就得涉及本地和服务器文件版本号等问题了。如果只是象你说的那中情况,能保证服务器发‘Ready’的时候客户端肯定在,那就是 gzmhero(hihihi) 所说了
      

  14.   

    大侠,有一问题,客户端在线程中循环读?如果服务器端不发送数据,则客户端就会一直停留在readln这条语句上,就像是死机了。并且后面服务器端发送了ready给客户端,客户端也没反应了。
    是不是客户端也要一直发送数据呢?
      

  15.   

    应该不会一直停留在readln里,会有超时的异常。循环读,应该能读到Ready的。
      

  16.   

    但我在程序中遇到过这种情况,如果服务器端不发送数据,而客户端readln,则客户端就一直停在readln上面了。
      

  17.   

    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;gzmhero(hihihi) 大侠,还是不行,服务器端在下面这条语句报错,
        sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
    "其他程序正在使用该文件..."
      

  18.   

    sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
    "其他程序正在使用该文件..."////////////////
    文件权限出了问题,其他程序正打开这个文件,所以不能读出。不是程序逻辑的问题。
    看一下是不是你的其他程序正在使用这个文件。
      

  19.   

    大侠,还是不行,我就用您上面的那段代码进行测试,还是不能进行多个客户端传输,当第二个连接到服务器时,在服务器上可以显示到第二个客户端的地址,但
    在第二个客户端就会报错:Connection Closed Gracefully.
    第一个客户端传送正常
      

  20.   

    是服务端的OnExecute事件里面造成,当函数里面出现了异常,连接关闭。
    还是文件操作的问题。
    服务端改成这样:var
        sFile:TFileStream;
        sv:TIdStreamVCL;procedure TForm1.FormShow(Sender: TObject);
    begin
        IdTcpServer1.Active:=true;
        sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
        sv:=TIdStreamVCL.Create(sFile,true);
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
        IdTcpServer1.Active:=false;
        sFile.Free;
    end;procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    begin
        sFile.Position:=0;
        AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
        AContext.Connection.IOHandler.Write(sv,sFile.Size);
    end;
      

  21.   

    还是帮人帮到底吧。服务端再改一下,主要是文件打开的模式:procedure TForm1.FormShow(Sender: TObject);
    begin
        IdTcpServer1.Active:=true;
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
        IdTcpServer1.Active:=false;
    end;procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var
        sFile:TFileStream;
        sv:TIdStreamVCL;
    begin
        sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead+fmShareDenyWrite);
        sv:=TIdStreamVCL.Create(sFile,true);
        AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
        AContext.Connection.IOHandler.Write(sv,sFile.Size);
        sFile.Free;
    end;
      

  22.   

    gzmhero(hihihi)大侠,您批评的对!
    我看了INDY的英文帮助,单看IdTCPServer和IdTCPClient这二个组件的帮助,看得很糊涂!文件的打开当时我也想了一下,因为是文件打开为读fmpopenread,所以觉得这样打开文件应该不会错。我总是想在这二个组件上了。我是第一次用网络组件开发,所以有许多地方不懂,还得请您和其他大侠指点,代码我其实也不想知道,我只想知道解决的思路,但以前没开发过网络这方面程序,思路上很糊涂!
    很感谢您这样全力的帮助!谢谢!分数奉上!