做一个代理程序,用两个serversocket,一个接收服务端发过来的数据,转发给终端设备,另一个接收终端设备发过来的数据,转发给服务端,现在的问题是,当一传数据的时候,界面就不动了,不想用Application.ProcessMessages;所以想用多线程来解决,但以前没搞过,没有思路,希望高手指点一下,先谢谢拉!~

解决方案 »

  1.   

    Indy有一个TIdTCPPortMapper简单多了。
      

  2.   

    没找到呀,我是delphi 6,能详细说一下吗,能发个例子更好
      

  3.   

    你找找这本书的第八章代码,有针对行的参考《Delphi深度编程及其项目应用开发》,他的官方出版社中国水利水电出版社网站也有
      

  4.   

    在Indy servers 下的IdMappedPortTcp
      

  5.   

    unit Communication;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ScktComp, Menus, ComCtrls, StdCtrls, ExtCtrls,
      IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdTCPServer, DiskList;//每次传送的最大字节数
    const MaxBufferSize = 100;//返回确认标记
    const returnconfirm = '!@#$';
    type
      //用于接收数据
      TIdcommserver = class(TIdTCPServer)
        procedure commExecute(AThread: TIdPeerThread);
      end;type
      //用于发送数据的线程
      TsendThread = class(TThread)
      protected
        procedure execute; override;
      end;//初始化客户端
    function initClientConnect(const host: string; const port: integer; const AFileName: string; const AFilesize: longint): boolean; export;
    //关闭客户端
    procedure desClientConnect; export;
    //客户端向磁盘文件写数据
    function ClientWriteBuffer(var Abuffer; const aBuffersize: integer): integer; export;
    //初始化服务器端
    function initServerConnect(const port: integer; const AFileName: string; const AFilesize: longint): boolean; export;
    //断开服务器端连接
    procedure desserverconnect; export;
    //服务器端从磁盘队列读出数据
    function serverreadbuffer(var buffer; var buffersize: longint): boolean; export;var
      IdCommClient: TIdTcpClient; //客户端Socket组件
      IdCommServer: TIdCommServer; //服务器端socket组件
      clientcommqueue: TcommQueue; //客户端磁盘队列
      servercommqueue: TcommQueue; //服务器端磁盘队列
      recvstream: TMemorystream; //接收的内存流
      sendthread: TsendThread; //发送线程
    implementation//监视发送队列,发现磁盘队列不为空,就进行发送;procedure TSendThread.execute;
    var
      buffersize: longint;
      frontposition, buffsize: longint;
      sendbuffer: pchar;
      i: longint;
      divbuffer: array[1..maxbuffersize + 5] of char;
      recvaccount: integer;
      recvbuffer: array[0..3] of char;
      ss: string;
      connectAgain: boolean;
    begin
      connectAgain := false;
      while not terminated do
      begin
        sleep(10);
        //判断磁盘队列是否为空
        if clientCommqueue.empty = 1 then
          continue;
        //判断是否重新连接
        if connectAgain = true then
        begin
          try
            IdCommClient.Disconnect;
            idcommclient.Connect;
          except
            continue;
          end;
        end;
        //得到头指针
        frontposition := clientcommqueue.frontpointer;
        //得到读出队列的大小
        clientcommqueue.readbuffersize(frontposition, buffersize);
        //分配sendBuffer缓冲区
        getmem(sendbuffer, buffersize);
        try
          //读出队列
          clientcommqueue.readQueue(sendbuffer^, buffersize);
          //判断是否段开发送
          if Buffersize > Maxbuffersize then
          begin
            for I := 1 to Buffersize div Maxbuffersize do
            begin
              buffsize := maxbuffersize + 1;
              move(buffsize, divbuffer[1], 4);
              move(sendbuffer[(I - 1) * maxbuffersize], divbuffer[5], maxbuffersize);
              //最后一位代表还未发完,'Y'代表一条队列内容已发完
              divbuffer[maxbuffersize + 5] := 'N';
              try
                IdCommClient.WriteBuffer(divbuffer, maxbuffersize + 5, true);
              except
                connectagain := true;
                continue;
              end;
              sleep(10);
            end;
            buffsize := (buffersize mod maxbuffersize) + 1;
            move(buffsize, divbuffer[1], 4);
            move(sendbuffer[(I - 1) * maxbuffersize], divbuffer[5], Buffersize mod maxbuffersize);
            divbuffer[(buffersize mod maxbuffersize) + 5] := 'Y';
            try
              IdCommClient.WriteBuffer(divbuffer, (Buffersize mod maxbuffersize) + 5, true);
            except
              connectagain := true;
              continue;
            end;
          end
          else
          begin
            buffsize := buffersize + 1;
            move(buffsize, divbuffer[1], 4);
            move(sendbuffer[0], divbuffer[5], buffersize);
            divbuffer[buffersize + 5] := 'Y';
            try
              IdCommClient.WriteBuffer(divbuffer, Buffersize + 5, true);
            except
              connectagain := true;
              continue;
            end;
          end;
          if idcommclient.ReadFromStack(true, 1000, true, nil) <> 4 then
            continue;
          ss := idcommclient.ReadString(4);
          //如果未发送成功,则回写
          if ss <> returnconfirm then
            clientcommqueue.writeQueue(sendbuffer^, buffersize);
        finally
          freemem(sendbuffer);
        end;
      end;
    end;//初始化客户端连接,并且指定磁盘队列;function initclientconnect(const host: string; const port: integer; const AFileName: string; const AFilesize: longint): boolean;
    begin
      //创建客户端的indy组件
      IdCommClient := TIdTCPClient.Create(nil);
      result := true;
      if IdCommClient.Connected = true then
        exit;
      //打开socket,并连接服务器
      IdCommClient.Host := host;
      IdCommClient.Port := port;
      try
        IdCommClient.Connect;
      except
        result := false;
      end;
      //创建客户端磁盘队列
      clientCommQueue := TcommQueue.Create(nil);
      //打开磁盘队列
      if clientcommqueue.open(AFilename, AFilesize) <> 1 then
        result := false;
      //创建发送监送线程
      sendthread := Tsendthread.create(false);
    end;//客户端发送缓冲区,并进行队列处理;function ClientWriteBuffer(var Abuffer; const aBuffersize: integer): integer;
    var
      I: integer;
    begin
      result := 1;
      //写队列
      if clientcommqueue.writequeue(abuffer, aBuffersize) <> 1 then
      begin
        result := -1; //写队列出错
        exit;
      end;
    end;//断开客户端连接,并关闭磁盘队列;procedure desclientconnect;
    begin
      //发送监视线程终止
      sendThread.Terminate;
      //断开连接
      if IdCommClient.Connected = true then
        IdCommClient.Disconnect;
      IdCommClient.Free;
      //关闭磁盘队列
      clientcommqueue.close;
    end;//初始化服务器端监听,并且指定接收磁盘队列;function initserverconnect(const port: integer; const AFileName: string; const AFilesize: longint): boolean;
    begin
      //创建服务器端socket
      IdCommServer := TIdcommServer.Create(nil);
      result := true;
      IdCommServer.OnExecute := IdCommServer.commexecute;
      if IdCommServer.active = true then
        exit;
      //打开服务器端socket,并开始监听连接
      IdCommServer.DefaultPort := port;
      try
        IdCommServer.active := true;
      except
        result := false;
      end;
      recvstream := TMemoryStream.create;
      //创建服务器端磁盘队列
      servercommqueue := Tcommqueue.Create(nil);
      //打开磁盘队列
      if servercommqueue.open(AFileName, AFilesize) <> 1 then
        result := false;
    end;//服务器端接收事件procedure TIdcommserver.commexecute(AThread: TIdPeerThread);
    var
      recvsize: integer;
      buffer: pchar;
      recvbuffer: pchar;
    begin
      //接收数据,一开始接收发送的数据区的大小
      Athread.Connection.ReadBuffer(recvsize, 4);
      getmem(buffer, recvsize);
      try
        Athread.Connection.Readbuffer(buffer^, recvsize);
        //判断最后一位是'Y'还是'N',以此代表是否发送完
        if (recvStream.Size = 0) and (buffer[recvsize - 1] = 'Y') then
        begin
          if servercommqueue.writequeue(buffer^, recvsize - 1) = 1 then
            Athread.Connection.Write(returnconfirm);
        end
        else if not assigned(recvstream) and (buffer[recvsize - 1] = 'N') then
        begin
          recvstream.WriteBuffer(buffer^, recvsize - 1);
        end
        else if assigned(recvstream) and (buffer[recvsize - 1] = 'N') then
        begin
          recvstream.WriteBuffer(buffer^, recvsize - 1);
        end
        else if (assigned(recvstream)) and (buffer[recvsize - 1] = 'Y') then
        begin
          recvstream.Write(buffer^, recvsize - 1);
          try
            getmem(recvbuffer, recvstream.size);
            recvstream.Seek(0, soFromBeginning);
            recvstream.ReadBuffer(recvbuffer^, recvstream.Size);
            if servercommqueue.writequeue(recvbuffer^, recvstream.Size) = 1 then
              //回发收到信息
              Athread.Connection.Write(returnconfirm);
            freemem(recvbuffer, recvstream.size);
          finally
            recvstream.Clear;
          end;
        end;
      finally
        freemem(buffer);
      end;
    end;//服务器端读队列function serverReadBuffer(var buffer; var buffersize: longint): boolean;
    begin
      result := true;
      if not servercommqueue.readQueue(buffer, buffersize) = 1 then
        result := false;
    end;//服务器端断开连接procedure desServerConnect;
    begin
      if IdCommServer.Active = true then
        IdCommServer.Active := false;
      IdCommServer.Free;
      recvstream.Free;
        //关闭磁盘队列
      servercommqueue.Free;
    end;end.
      

  6.   

    hThread:=CreateThread(nil,0,@ComProc,nil,0,ThreadId);//ComProc为调用的函数
    用CreateThread创建两个进程,专门处理收发,不要在主线程里面做收发,要不然有数据进就是死循环了
      

  7.   

    接分
    PS: 
    我的目标是 ----> ^_^
      

  8.   

    接分
    PS: 
    我的目标是 ----> ^_^
      

  9.   

    接分..
    PS: 
    我的目标是 ----> ^_^
      

  10.   

    怎么 没什么印象 这是delphi?
      

  11.   

    不知道你用什么语言,说下思路吧,就是在你初始化窗口的线程中开一个线程用来不断判断程序的状态(当然你要给你的程序设置不同的状态值,比如说,建立连接一个状态,发数据一个状态,一便以后有程序改变状态(比如如果发送的时候socket链接断了,可以转移到建立socket的状态去再建立)),在这个新开的线程中再开建立socket的线程和接发数据的线程,接受到的数据存储到一个buff里面,之后当buff里面有数据的时候你就可以发送出去了。这些收发数据的线程里面肯定都是要用死循环的,所以最好用信号量来控制起来,这样在没有数据可收发的时候就可以节省一些资源。还有就是buff要用临界区封起来,不然会出现问题。注意到这几点应该整个程序的框架就搭建起来了。能跑了。再调调就差不多了。
      

  12.   

    没找到呀,我是delphi 6,能详细说一下吗,能发个例子更好
      

  13.   

    在Indy servers 下的IdMappedPortTcp