本来这应该是个很简单的问题,但是ServerSocket把它连接列表FConnections做成private的里,外部不能访问。要知道要知道ClientSocket的index 有两种方法
1,做个循环,从0到 ActiveConnections-1 找一遍;
2,用个Tlist来记录每一个ClientSocket,在建立连接时添加到列表,断开时删除。但ClientSocket的index可能是变化的,特别是在client比较多的时候,以为服务器不断产生连接和断开,ClientSocket在FConnections队列的位置也在变,我想这可能是TServerSocket没有取ClientSocket index的属性和方法的原因吧。 要向多个连接发送信息,在阻塞模式,由各个子线程负责,在非阻塞模式,只能排队,做个循环挨个发送。

解决方案 »

  1.   

    请问您是否有 使用 TServerSocket 开发 组塞模式 多线程 的例子?
      

  2.   

    serverunit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ScktComp, StdCtrls;
      
    type
      TMyServerThread = Class(TServerClientThread)
       public
          procedure ClientExecute;override;
      end;
      
      TForm1 = class(TForm)
        SS: TServerSocket;
        Memo1: TMemo;
        Button1: TButton;
        Button2: TButton;
        ListBox1: TListBox;
        procedure SSClientRead(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure Button1Click(Sender: TObject);
        procedure SSThreadStart(Sender: TObject; Thread: TServerClientThread);
        procedure SSGetThread(Sender: TObject;
          ClientSocket: TServerClientWinSocket;
          var SocketThread: TServerClientThread);
        procedure SSThreadEnd(Sender: TObject; Thread: TServerClientThread);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.DFM}procedure TMyServerThread.ClientExecute;
    Var
      Data: Array[0..1023] Of char;
      RecText: String;
      SocketStream: TWinSocketStream;
    Begin
      While Not Terminated And ClientSocket.Connected Do
      Try
        SocketStream := TWinSocketStream.Create(ClientSocket, 5000);
        Try
          FillChar(Data, SizeOf(Data), #0);
          SocketStream.WaitForData(5000);
          If SocketStream.Read(Data, SizeOf(Data)) = 0 Then
          Begin
            ClientSocket.SendText('Timeout on Server');
            sleep(1);
            ClientSocket.Close;
            Terminate;
          End;
          RecText := Data; 
          If Length(RecText) > 2 Then
            Delete(RecText, Pos(#13#10, RecText), 2); // Delete #13#10 
          If ClientSocket.Connected Then
          Begin
            ClientSocket.SendText(RecText);
            SendMessage(Form1.Listbox1.Handle, LB_ADDSTRING, 0, Integer(PChar(RecText)));
            //PostMessage(Form1.Handle, CM_INCCOUNT, 0, 0);
          End;
        Finally
          SocketStream.Free;
        End;
      Except
        HandleException;
      End;
    End;
    procedure TForm1.SSClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
       Memo1.Lines.Add('Client Will to Write');
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
       SS.Open;
       Memo1.Lines.Add('Listen..');
    end;procedure TForm1.SSThreadStart(Sender: TObject;
      Thread: TServerClientThread);
    begin
       Memo1.Lines.Add('Thread Start');
       Memo1.Lines.Add(Thread.ClassName);
    end;procedure TForm1.SSGetThread(Sender: TObject;
      ClientSocket: TServerClientWinSocket;
      var SocketThread: TServerClientThread);
    begin
       TMyServerThread.Create(False,ClientSocket);
    end;procedure TForm1.SSThreadEnd(Sender: TObject; Thread: TServerClientThread);
    begin
       Memo1.Lines.Add('Thread End');
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
       SS.Close;
    end;end.
      
    client:
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ScktComp, ComCtrls, StdCtrls;type
      TMyClientThread = Class(TThread)
      private
        { Private declarations }
      protected
         procedure Execute; override;
      end;  TForm1 = class(TForm)
        CS: TClientSocket;
        Btn_Connect: TButton;
        StatusBar1: TStatusBar;
        Edit1: TEdit;
        Memo1: TMemo;
        btn_Send: TButton;
        Edit2: TEdit;
        Button1: TButton;
        procedure Btn_ConnectClick(Sender: TObject);
        procedure btn_SendClick(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.DFM}procedure TMyClientThread.Execute;
    var
       MyStream : TWinsocketStream;
       buffer : string;
       i : integer;
    begin
       buffer := Form1.Edit2.Text + #13#10;
       MyStream := TWinsocketStream.Create(Form1.CS.Socket,5000);
       try
          While (Not Terminated) and (Form1.CS.Active) do begin
             try
                MyStream.WaitForData(5000);
                i := MyStream.Write(buffer[1],Length(buffer)+1);
                Form1.Memo1.Lines.Add(inttostr(i));
                Terminate;
             except
             end;
          end;
       finally
          MyStream.Free;
       end;
    end;procedure TForm1.Btn_ConnectClick(Sender: TObject);
    begin
       if CS.Active then CS.Close;
       CS.Port := 2500;
       CS.ClientType :=  ctBlocking;
       CS.Host := Edit1.Text;
       try
          CS.Open;
          StatusBar1.SimpleText := 'Connected to ' + CS.Host;
       except
          StatusBar1.SimpleText := 'Error Connected to ' + CS.Host;
          Exit;
       end;
    end;procedure TForm1.btn_SendClick(Sender: TObject);
    begin
       TMyClientThread.Create(False);
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
       CS.Close;
    end;end.网上找到了,测试了一下,基本上是好的,有些小问题。