andyADD
andyADD

Reputation: 610

Delphi: Sending multiple strings through sockets?

I am currently using delphi 6 (yes, I know.. but its so far getting the job done.)

I am using Serversocket, and client socket. When I have my client connect to my server, I would like to have it send some info, like computername, lAN IP, OS name, ping.

At the moment I only have the client sending the computer name to the server, I am wondering how can I send multiple information, and set it up accordingly in my grid? here is the source code:

Client:

unit client1;

interface

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

type
  TForm1 = class(TForm)
    Client1: TClientSocket;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Client1Connect(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function Getusernamefromwindows: string;
var
iLen: Cardinal;
begin
 iLen := 256;
 Result := StringOfChar(#0, iLen);
 GetUserName(PChar(Result), iLen);
 SetLength(Result, iLen);
end;


function Getcomputernamefromwindows: string;
var
iLen: Cardinal;
begin
 iLen := MAX_COMPUTERNAME_LENGTH + 1;
 Result := StringOfChar(#0, iLen);
 GetComputerName(PChar(Result), iLen);
 SetLength(Result, iLen);
end;

function osver: string;
begin
result := 'Unknown';
case Win32MajorVersion of
4:
  case Win32MinorVersion of
  0: result := 'windows 95';
  10: result := 'Windows 98';
  90: result := 'Windows ME';
  end;
5:
  case Win32MinorVersion of
  0: result := 'windows 2000';
  1: result := 'Windows XP';
  end;
6:
  case Win32MinorVersion of
  0: result := 'Windows Vista';
  1: result := 'Windows 7';
  end;
end;
end;



procedure TForm1.FormCreate(Sender: TObject);
begin
   Client1.Host := '192.168.1.106';
   Client1.Active := true;

end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Client1.Active := false;
end;

procedure TForm1.Client1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
  Client1.Socket.SendText(Getcomputernamefromwindows + '/' + Getusernamefromwindows);
   (*Upon connection to server, I would like it send the os name, but as you
     can see I already have SendText being used*)

end;

end.

Server:

    unit server1;

interface


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

type
  TForm1 = class(TForm)
    Server1: TServerSocket;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    TabSheet3: TTabSheet;
    TabSheet4: TTabSheet;
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure Server1ClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);


  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}






procedure TForm1.FormCreate(Sender: TObject);
begin
 With StringGrid1 do begin

 Cells[0,0] := 'Username';
 Cells[1,0] := 'IP Address';
 Cells[2,0] := 'Operating System';
 Cells[3,0] := 'Ping';

 end;
end;

(* cells [0,0][1,0][2,0][3,0]
   are not to be changed for
   these are used to put the
   titles in
*)





procedure TForm1.Server1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var

begin

     with StringGrid1 do begin

   Cells[0,1] := Socket.ReceiveText;
   Cells[1,1] := Server1.Socket.Connections[0].RemoteAddress;
   (*in this area I want it to receive the os version info and place it in
     Cells[2,1]*)
   end;
end;

end.

Upvotes: 1

Views: 1315

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596166

You already know the answer, because you are already doing it. Send the various strings with delimiters in between them (in your example, you are using /, but you could also use CRLFs, string length prefixes, etc), and then some final delimiter to signal the end of the data.

The real problem with your code is the use of SendText() and ReceiveText(). SendText() is not guaranteed to send the entire string in one go. It returns how many bytes it actually sent. If fewer than your string length, you have to call SendText() again to send the remaining bytes. As for ReceiveText(), it just returns whatever arbitrary data is on the socket at that moment, which may be an incomplete string, or multiple strings merged together.

You are using lower-level I/O methods without first designing a higher level protocol to describe the data being sent. You need a protocol. Design how you want your data to look, then format your data that way and use the methods to send/receive that data, then break apart the data as needed when received.

So, in this case, you could send a single CRLF-delimited string that contains /-delimited values. The server would then read until it reaches the CRLF, then split the line and use the values according.

Upvotes: 7

Related Questions