那么,再问:
TServerSocket和TClienSocket 的多线程和同步问题:
  ServerSocket 用 多线程 吗?
请各位达人尽量详细说明,我在通讯上是菜鸟...哪里有例子??

解决方案 »

  1.   

    另外,TServerSocket和TClienSocket一般是放在同一个程序中,还分开两个程序??
      

  2.   

    TServerSocket 是用在服务端的, 当然是多线的, 在线程同步上, 可以是 block, noneblock, 不过 serverSocket对 block 的支持效果好, 因为它采用的是一线程一 socket handle . 不过有时线程数量多时, 又没什么界面回显时, 单用 ServerSocket 的事件就很难同步好, 这时就要派生一个新的 ServerSocket, 自已处理他的 ClientExecute 部分TClientSocket 一般用在客户机, 因为客户端的 socket 程序很好写, 所以我从不用这个组件
      

  3.   

    有点错, 更正一下, 派生的是 TServerClientThread比方 TMyServerThread = class(TServerClientThread)
    然后在 TServerSocket 的 OnGetThread 中写到
      SocketThread := TMyServerThread.Create(Self, ClientSocket);
      SocketThread.Resume;从 TServerClientThread 中派生的线程 的最主要方法就是 procedure ClientExecute; override;
      

  4.   

    TO:  comanche(太可怕) :  能不能给一段TserverSocket多线程的例子??
      

  5.   

    类申明  TTCPCollectorThread = class (TServerClientThread{, ITerminal})
      private
        ... //好多东东去掉了
        FLastActivity: TDateTime;
        function GetLastActivity: TDateTime;    function WaitForData(Timeout: Integer): TWaitResult;
      protected
        procedure ClientExecute; override;
        ...
      public
        constructor Create(ACollector: TTCPCollector; ASocket:
          TServerClientWinSocket);
        destructor Destroy; override;    property LastActivity: TDateTime read GetLastActivity;
      end;constructor TTCPCollectorThread.Create(ACollector: TTCPCollector; ASocket:
      TServerClientWinSocket);
    begin
      FLastActivity := Now;  inherited Create(true, ASocket);
    end;destructor TTCPCollectorThread.Destroy;
    begin
      ...
      inherited;
    end;procedure TTCPCollectorThread.ClientExecute;
    begin
      CoInitialize(nil); // 初始化 COM, 我的要操作 COM, 没有的去掉
      try
        while (not Terminated) and ClientSocket.Connected do
        begin
          try
            case WaitForData(3*60*1000{FCollector.Timeout}) of // 3分种          wrSignaled:
              begin
                FLastActivity := Now();
                // 有数据进来, 处理
              end;          wrTimeout: // 线程空闲超时
                break;          wrError:   // 由客户机关闭了连接
                break;
            end;
          except
            on e: Exception do
              // log 处理中的异常
          end;
        end;  finally
        // 加入清理代码, 在线程中的私有成员, 出了这个函数后, 线程不一定释放(ServerSocket 的 Cache 大小决定), 但 socket 关闭, 所以清除线程的私有成员上次使用的值
        CoUninitialize;
      end;
    end;function TTCPCollectorThread.WaitForData(Timeout: Integer): TWaitResult;
    var
      FDSet: TFDSet;
      TimeVal: TTimeVal;
      ReturnCode: Integer;
    begin
      FD_ZERO(FDSet);
      FD_SET(ClientSocket.SocketHandle, FDSet);
      TimeVal.tv_sec := Timeout div 1000;
      TimeVal.tv_usec := Timeout mod 1000;  ReturnCode := select(0, @FDSet, nil, nil, @TimeVal);  if ReturnCode > 0 then // client 有数据
      begin
        if ClientSocket.ReceiveLength <= 0 then result := wrError // 是 client 断线
        else result := wrSignaled
      end
      else if ReturnCode = 0 then
        result := wrTimeout                                       // 指定时间内没有数据
      else result := wrError; // 理论上不可能发生, 在设了带外数据后, 有带外数据, 也是用这个通知
    end;
      

  6.   

    上面这个就是线程本身, 然后在 ServerSocket 的 OnGetThread 中写到  SocketThread := TTCPCollectorThread.Create(Self, ClientSocket);
      SocketThread.Resume;组件还是用 ServerSocket, 只不过代替了他的线程部分
      

  7.   

    再比方          wrSignaled:
              begin
                FLastActivity := Now();
                // 有数据进来, 处理, 这里加几句
              end;这里加几句var
      str: string;SetLength(str, ClientSocket.ReceiveLength);
    ClientSocket.ReceiveBuf(PChar(str)^, ClientSocket.ReceiveLength)
    if str = 'hello' then
    begin
      str := 'world';
      ClientSocket.SendBuf(PChar(str)^, Length(str)); // 哈, 当然没那么简单, 不过也就是这样啦
    end;
      

  8.   

    作个简单 telnet, 下面是加的函数procedure TTCPCollectorThread.ClientExecute;
    var
      Operation: string;
      Command: string;
    begin
      CoInitialize(nil);
      try
        FLastActivity := Now;    while not Terminated and ClientSocket.Connected do
        begin
          case WaitForData(3*60*1000{ConnectionTimeout}) of
            wrSignaled:
            begin
              try
                Command := Receiveln;
                Operation := UpperCase(CmdParamStr(Command, 0));            if Operation = 'QUIT' then
                  break
                else if Operation = 'HELLO' then
                  Sendln('WORLD');
                ...
              except
    //            on e: Exception do
              end;          FLastActivity := Now;
            end;        wrTimeout: break;
            wrError: break;
          end;
        end;
      finally
        CoUninitialize;
      end;
    end;// 这个是分析来的命令, 一般格式是 COMMAND PARAMETERS, 跟 ParamStr 功能相近
    function TTCPCollectorThread.CmdParamStr(Command: string; Index: Integer): string;
    var
      ps, pe: PChar;
      len: Integer;
    begin
      result := '';  pe := PChar(Command);
      ps := pe;  while pe^ <> #0 do
      begin
        Inc(pe, 1);    if pe^ = ' ' then
        begin
          if Index = 0 then
          begin
            len := pe - ps;
            SetLength(result, len);
            Move(ps^, PChar(result)^, len);
            break;
          end
          else
          begin
            Dec(Index, 1);
            Inc(pe, 1);
            ps := pe;
          end;
        end;
      end;  if (pe^ = #0) and (ps <> pe) and (Index = 0) then
      begin
        len := pe - ps;
        SetLength(result, len);
        Move(ps^, PChar(result)^, len);
      end;
    end;const
      CRLF = #13#10; // 加在全局function Sendln(s: string; const eol: string = CRLF): Integer; // 加在线程里function TManagementThread.Sendln(s: string; const eol: string): Integer;
    begin
      s := s + eol;
      Result := ClientSocket.SendBuf(pchar(s)^, length(s));
    end;
    function TManagementThread.Receiveln(const eol: string): string;
    var
      len: Integer;
      buf: array[0..2100] of char;
      eolptr: pchar;
    begin
      Result := '';
      eolptr := nil;
      repeat
        if WaitForData(1*60*1000{OperationTimeout}) <> wrSignaled then
        begin
          result := 'QUIT'; // 当作退出
          exit;
        end;    len := ClientSocket.PeekBuf(buf, sizeof(buf) - 1);
        if len > 0 then
        begin
          buf[len] := #0;
          eolptr := strpos(buf, pchar(eol));
          if eolptr <> nil then
            len := eolptr - buf + length(eol);
          ClientSocket.ReceiveBuf(buf, len);
          if eolptr <> nil then
            len := len - length(eol);
          buf[len] := #0;
          Result := Result + buf;
        end;    if len > 2100 then // command too long
          raise Exception.Create('SEInvalidDataPacket');  until (len < 1) or (eolptr <> nil);
    end;
      

  9.   

    定义忘了    function Receiveln(const eol: string = CRLF): string; 起动后, 比方你 ServerSocket 的端口设 1024程序运行... telnet 127.0.0.1 1024
    试试 HELLO
      

  10.   

    又发现一些错, 全部 TManagementThread. 都是 TTCPCollectorThread. 这些全是加在你自定的类里名字随你取啦