开发者

TServerSocket and Many TClientSocket

开发者 https://www.devze.com 2023-02-07 11:19 出处:网络
I have one TserverSocket and many TClientSocket. A can SendText from all Client to the server and receive it corectly.

I have one TserverSocket and many TClientSocket. A can SendText from all Client to the server and receive it corectly. But the开发者_如何学编程 problem is how to send different data from TServerSocket to many different Clients.


Each client is stored in the server's Connections list. Simply locate the TCustomWinSocket object for the particular client that you want to send to. Socket connections are identified at the OS layer by the two IP/Port pairs (local and remote) that they use. Or you can assign more meaningful IDs (a username, etc) to each client's TCustomWinSocket.Data property instead.


I'm not completely sure I understand the question, but I've written this solution:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ScktComp;

type
  TForm1 = class(TForm)
    ServerSocket1: TServerSocket;
    procedure ServerSocket1Accept(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  hnd:array[1..1024] of integer;
  txt:array[1..1024] of string;
  ser,counter : integer;
implementation

{$R *.dfm}

procedure TForm1.ServerSocket1Accept(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  ser:= Socket.SocketHandle;
    inc(counter);
    hnd[counter]:=ser;
    txt[counter]:='You are number '+IntToStr(counter);
end;


procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
 var t:Integer;
begin
    ser:= Socket.SocketHandle;
    for t:=1 to counter do
    begin
      if hnd[t]=ser then socket.SendText(txt[t]+#13);
    end;
end;

end.

Does this work for you?


The easiest way to manage/identify client socket connections is to use their unique socket handle.

var connectedSocketHandle : integer;
.
.
.
TForm1.server1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);

begin
    connectedSocketHandle:= Socket.SocketHandle; {<--- this is the socket handle of the      client that just connected ..}    
end;

 procedure TForm1.SendMsgToOneSpecificClient(const MsgData: string;
    SocketServer: TServerSocket; uniqueSocketHandle: integer);
 begin
   for x := 0 to socket.Socket.ActiveConnections - 1 do
    begin
      try
        if SocketServer.Socket.Connections[x].SocketHandle = uniqueSocketHandle then
          SocketServer.Socket.Connections[x].SendText(MsgData);
      except
          {....}
      end;
    end;
end;


I realize this answer is way LATE, however I just felt that someone should step in and give an actual Written answer here just in case someday others come seeking the same information.

FYI anyone viewing this PLZ take a good look at what "Remy Lebeau" said in his answer he is 100% correct he just didn't leave any source code to go by.

Ok so lets get started, basically in order to "Send to Specific Clients from a TServerSocket" you must design your own "List" of connections and apply them to the Tcustomwinsock.Data property of each connecting TClientSocket as Remy said in his answer.

If you do not understand so far just keep reading i'm sure all will be made quite clear in a moment.

at the top of your Delphi server application add the following TYPE Record:

type TConnectionInfo = record
                          UserID : string;
                          Socket : TCustomWinSocket; // THIS IS VERY IMPORTANT!!! Do not FORGET it
                   end;

After you have created the TConnectionInfo Reccord you can move on to the next part witch is to create a "Pointer" to the TconnectionInfo Reccord so under your Private or public Declarations you could simply add:

var
Connection: ^TConnectionInfo;

once you have done that we can move onto the ServerSocketClientConnect Event procedure where we will start to build up the list of connections via the TConnectionInfo Reccords < there will be one for every single connected Client.

so the serversocketclientconnect event procedure should look sompthing like this:

procedure TfMain.ServerSocketClientConnect(Sender: TObject; Socket: TCustomWinSocket);
Begin

       GetMem(Connection,sizeof(TConnectionInfo));
       try
       Connection^.UserID := ServerSocket.reciveText; //So when someone connects make them send their username / ID or whatever
       Connection^.Socket := Socket; // This is the important part you will be setting the current socket connection to the "TCustomWinsock" for this connection.
       Socket.Data := Connection; // Now comes the part where you assign the Tcustomwinsock.data property to This instance of the Connection Reccord
       except
       freemem(Socket.Data);
       socket.Close;
       end;
       end;
end;

Ok so if your following me so far, next comes the fun part that you where asking about "How to send to specific Client" well once you have the above code setup it is extremely easy to send to just one specific client via thier "UserID" as coded above. For the sake of simplicity i'm just going to put this in a Button Click Event procedure:

Procedure TForm1.Button1Click(Sender: TObject);
var 
scan: integer; // scan is the integer count used to Gather all the active connections.
tempcon: ^TConnectionInfo; // Tempcon is going to be used as a pointer to the Connection reccords so we can go though them and send to only a specific Client via his or her UserID :) 
      begin
      try
        for scan := 0 to ServerSocket.Socket.ActiveConnections-1 do
          begin
            TempCon := ServerSocket.Socket.Connections[scan].Data;
            if (TempCon^.UserID = 'The User ID of the person you want to send to') then
               ServerSocket.Socket.Connections[scan].SendText( 'Text you want to send to them!' ); // and this is where the serversocket will send to only one Person via their TcustomWinsock.data property and it will only send to the user with the UserID you specified in the line above.
          end;

Now Remember just because you are able to send as you want to now, you are still not yet finished. you must understand that because you are using your own custom list of Reccords for each connection you must also "Free" that memory accordingly as each Client disconnects from the server.... so like this:

procedure TfMain.ServerSocketClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);

begin
  freemem(Socket.Data); // so this code will Free the socket.data which is actually the Record associated with this specific Client Connection.
end;

I hope this helps the Poster and anyone else who may come seeking information as to how to properly manage clients connected to the TServerSocket vcl Component.


If I recall, and I haven't used Delphi for quite some time, TServerSocket has a list of clients you can access, check the properties.

You can also add/remove the TCustomSocket instance to a list when the client connections/disconnects and then just iterate that and send there, though like I said, I'm pretty sure TServerSocket has this internally anyhow.


You can use the excellent (free ) ICS library http://www.overbyte.be/, with it you have a good example of a TCP server with multiple clients.

0

精彩评论

暂无评论...
验证码 换一张
取 消