Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Winsock Example Frage (https://www.delphipraxis.net/153641-winsock-example-frage.html)

CoYoTE 11. Aug 2010 00:37


Winsock Example Frage
 
Hallo
versuche anhand des Internets Google mit Tutorials Delphi zu lernen.
Nun das ist das erstemal das ich mich überhaupt an ein Forum wende Sonst habe ich immer alles geschafft mit Google.
Google hat mir Z.b. php beigebracht.
Ich komme nun leider überhaupt nicht weiter weis nicht was falsch ist an dem Code schnipsel.
der Client funktioniert eben dieser Teil hier nicht.
Wäre echt geil wen sich das mal ein Profi anguggt und mir sagt was daran falsch ist und mir erklärt wie ich das Problem behebe. Brauche Hilfe ich probiere seit 3 Tagen dran rum lol ich gebe erstmal nicht auf mal sehen woran es liegt.
hier der Code:

Delphi-Quellcode:
program prjServer;

{$APPTYPE CONSOLE}

uses
  Winsock,
  Windows,
  SysUtils;
type
  TDynStringArray = array of AnsiString;

type
  TServer = class(TObject)
  Private
    hSocket: TSocket;
    Addr:    TSockAddrIn;
    wsaData: TWSAData;
  Public
    procedure Connect;
    procedure SendData(Data: AnsiString);
    procedure ReceiveData(Socket: TSocket; Buffer: PByte);
    function UserName(): AnsiString;
    function CompName(): AnsiString;
    function GetIPFromHost(const HostName: AnsiString): AnsiString;
    function Explode(const Separator, S :AnsiString; Limit :Integer = 0): TDynStringArray;
end;

var
  Server:  TServer;
  Close:   Boolean;

  //Connection settings
  hPort: Integer;
  hHost: AnsiString;


procedure TServer.ReceiveData(Socket: TSocket; Buffer: PByte);
var
  Data: AnsiString;
  strArr: TDynStringArray;
begin

  //Convert our data to a AnsiString and trim it
  Data := AnsiString(Buffer);
  Data := Trim(Data);

  if Length(Data) > 0 then begin

  //Setup our dynamic array structure
  StrArr := Explode('|', Data);

  //Display incoming message (if strArr[0] = 'MSGBOX')
  if StrArr[0] = 'MSGBOX' then begin
   MessageBox(0,PAnsiChar(StrArr[1]),'Winsock Example',MB_OK + MB_ICONINFORMATION)
  end;

end;
end;

procedure TServer.Connect;
var
  Buffer: Array[0..8192] Of AnsiChar;
  iRecv: Integer;
Begin
  if (WSAStartup($0202, wsaData) <> 0) then
  begin

    Writeln('Unable to start winsock, unable to continue');
    Readln;

    Exit;
  end;
  Close := False;
  repeat

    //Prepare a listen socket to be used for our connection
    //and declare its host/port information
    hSocket := Socket(AF_INET, SOCK_STREAM, 0);
    Addr.sin_family  := AF_INET;
    Addr.sin_port    := htons(hPort);
    Addr.sin_addr.S_addr := INET_ADDR(PAnsiChar(GetIPFromHost(hHost)));

    Writeln('Connecting to ' + GetIPFromHost(hHost));

    //Attempt the connection using our socket
    if (Winsock.Connect(hSocket, Addr, SizeOf(Addr)) = 0) then
    begin

      Writeln('Connected to host');

      //Notify our connected client of the connection and send
      //our information
      SendData('ADDNEW|' + UserName + '|' + CompName + '|' + 'Awaiting commands');

      //Attempt to receive data from our socket.
      ZeroMemory(@Buffer, SizeOf(Buffer));
      iRecv := Recv(hSocket, Buffer, SizeOf(Buffer), 0);
      while ((iRecv > 0) and (iRecv <> INVALID_SOCKET)) do
      begin
        ReceiveData(hSocket, @Buffer);
        ZeroMemory(@Buffer, SizeOf(Buffer));
        iRecv := Recv(hSocket, Buffer, SizeOf(Buffer), 0);
      end;

      //We got disconnected if we reach this point
      Writeln('Lost connection');
      CloseSocket(hSocket);
    end;

    //Wait 3 seconds and repeat our connection attempt
    Sleep(3000);
   until (Close);
  WSACleanup();
end;

function TServer.UserName(): AnsiString;
var
  User : array[0..255] of AnsiChar;
  SizeOfUser : Cardinal;
begin
  SizeOfUser := SizeOf(User);
  if GetUserName(User, SizeOfUser) = True then
    Result := AnsiString(User)
  else
  Result := 'Unknown';
end;

function TServer.CompName(): AnsiString;
var
  Comp : array[0..255] of AnsiChar;
  SizeOfComp : Cardinal;
begin
  SizeOfComp := SizeOf(Comp);
  if GetComputerName(Comp, SizeOfComp) = True then
    Result := AnsiString(Comp)
  else
  Result := 'Unknown';
end;

function TServer.GetIPFromHost(const HostName: AnsiString): AnsiString;
type
  TaPInAddr = array[0..10] of PInAddr;
  PaPInAddr = ^TaPInAddr;
var
  phe: PHostEnt;
  pptr: PaPInAddr;
  i: Integer;
begin
  Result := '';
  phe := GetHostByName(PAnsiChar(HostName));
  if phe = nil then Exit;
  pPtr := PaPInAddr(phe^.h_addr_list);
  i := 0;
  while pPtr^[i] <> nil do
  begin
    Result := inet_ntoa(pptr^[i]^);
    Inc(i);
  end;
end;

//This function splits up a given AnsiString into an array
function TServer.Explode(const Separator, S :AnsiString; Limit :Integer = 0): TDynStringArray;
  var
    SepLen: Integer;
    F, P: PAnsiChar;
begin
  SetLength(Result, 0);
  if (S = '') or (Limit < 0) then
    Exit;
  if Separator = '' then
    begin
      SetLength(Result, 1);
      Result[0] := S;
      Exit;
    end;
  SepLen := Length(Separator);

  P := PAnsiChar(S);
  while P^ <> #0 do
    begin
      F := P;
      P := AnsiStrPos(P, PAnsiChar(Separator));
      if (P = nil) or ((Limit > 0) and (Length(Result) = Limit - 1)) then
        P := StrEnd(F);
      SetLength(Result, Length(Result) + 1);
      SetString(Result[High(Result)], F, P - F);
      F := P;
      if P = Separator then
        SetLength(Result, Length(Result) + 1);
      while (P^ <> #0) and (P - F < SepLen) do
        Inc(P);
    end;
end;

procedure TServer.SendData(Data: AnsiString);
var
  Len: LongInt;
begin
  Len := Length(Data);
  Send(hSocket, Data[1], Len, 0);
end;

begin

  Server := TServer.Create;
  hHost := '127.0.0.1';
  hPort := 12345;

  Server.Connect;
end.

fkerber 11. Aug 2010 00:47

AW: Anfänger am Werk HILFEEEEE!!
 
Hallo!

Herzlich willkommen in der DP.

Gleich zu Beginn 2 Bitten:
*) Ändere bitte deinen Titel (editieren des ersten Beitrags, erweiterter Editor) - Hilfe suchen hier fast alle, schreien (Großschreibung) wird als unhöflich empfunden und der Titel sollte das Problem charakterisieren.

*) Bitte verwende für deine Delphi-Codes immer Delphi-Tags.


Liebe Grüße,
Frederic

XHelp 11. Aug 2010 00:50

AW: Anfänger am Werk HILFEEEEE!!
 
Es könnte bei der Aufklärung helfen, wenn du verrätst was nicht funktioniert, wo der Fehler liegt, was du erwartest o.ä.

P.S. Und Delphi-Tags sollte man nicht zusätzlich zu dem einfach so kopierten Quelltext nutzen, sondern stattdessen ;)

xZise 11. Aug 2010 07:45

AW: Anfänger am Werk HILFEEEEE!!
 
Moin,
ist natürlich nicht hilfreich, wenn wir bisher nicht helfen konnten, allerdings frage ich mich gerade, wieso du deinen Sourcecode zweimal gepostet hast.

Und deine Frage wäre cool. (Ab dann kann dir auch geholfen werden i.d.R.)

MfG
Fabian

blackfin 11. Aug 2010 08:26

AW: Anfänger am Werk HILFEEEEE!!
 
Ich glaube, du hast ausversehen zweimal den Server-Quellcode gepostet anstatt jeweils Server und Client.

Generell wäre es sicher für "uns" hilfreich, wenn du dein Problem noch etwas spezifizierst.
Es ist auch allgemein eine gute Idee, bei der Beschreibung eines Problems erst einmal kurz und knapp zu erläutern, was das Programm eigentlich machen soll und was dabei nicht funktioniert.
Auch wenn hier einige "Profis" sind, so ist oft bei einem zwei Seiten langen Quellcode nicht auf den ersten Blick ersichtlich, was der Code eigentlich ausführen soll. In diesem Fall handelt es wohl um einen Servercode, der Daten von einem Client empfangen und zu diesem senden soll.
Was funktioniert daran nicht?

fkerber 11. Aug 2010 08:29

AW: Anfänger am Werk HILFEEEEE!!
 
Hi!

Allgemein wäre es auch besser, nur für das Problem relevante Teile zu zeigen, anstatt Unmengen von Code, die vllt. gar nix mit dem Fehler zu tun haben.


Liebe Grüße,
Frederic

DeddyH 11. Aug 2010 08:32

AW: Anfänger am Werk HILFEEEEE!!
 
Wie stelle ich Fragen richtig?

CoYoTE 11. Aug 2010 09:50

AW: Winsock Example Frage
 
Okay gut sage ja ich bin das erstemal in einem Forum sorry deswegen.

Also es geht darum.
dieses beample wo ich im Internet gefunden habe wurde in der Delphi Version 2006 gemacht.
um es zum laufen zubringen für Delphi Version 2009 musste man folgendes ändern.
String = AnsiString
PChar = PAnsiChar
Char = AnsiChar
Das habe ich gemacht und der Client lief.
bei dem Server habe ich nun folgendes Problem:

Inkompatible Typen AnsiChar und Char. wen ich hier wieder PCar Anstatt PAnsiChar Mache geht das. mit den Compilieren weiter
Delphi-Quellcode:
if StrArr[0] = 'MSGBOX' then begin
   MessageBox(0,PAnsiChar(StrArr[1]),'Winsock Example',MB_OK + MB_ICONINFORMATION)
  end;
end;
Inkompatible Typen Array und PWideChar wen ich hier aus AnsiChar Ein PWideChar Mache geht es. weiter mit dem Compilieren.
Delphi-Quellcode:
function TServer.UserName(): AnsiString;
var
  User : array[0..255] of AnsiChar;
  SizeOfUser : Cardinal;
begin
  SizeOfUser := SizeOf(User);
  if GetUserName(User, SizeOfUser) = True then
    Result := AnsiString(User)
  else
  Result := 'Unknown';
end;
Das selbe gilt für hier:
Delphi-Quellcode:
function TServer.CompName(): AnsiString;
var
  Comp : array[0..255] of AnsiChar;
  SizeOfComp : Cardinal;
begin
  SizeOfComp := SizeOf(Comp);
  if GetComputerName(Comp, SizeOfComp) = True then
    Result := AnsiString(Comp)
  else
  Result := 'Unknown';
end;
Gut nun funktioniert es und der Server startet und man kann sich au verbinden.
Wen ich nun Aber eine Message vom Client schicke auf den Server (MSGBOX).
Kommen nur Fragezeichen an wen ich es mir mit dem Debugger anschaue nämlich hier an dieser Stelle:
Delphi-Quellcode:
procedure TServer.ReceiveData(Socket: TSocket; Buffer: PByte);
var
  Data: AnsiString;
  strArr: TDynStringArray;
begin

  //Convert our data to a AnsiString and trim it
  Data := AnsiString(Buffer);
  Data := Trim(Data);

  if Length(Data) > 0 then begin

  //Setup our dynamic array structure
  StrArr := Explode('|', Data);

  //Display incoming message (if strArr[0] = 'MSGBOX')
  if StrArr[0] = 'MSGBOX' then begin
   MessageBox(0,PChar(StrArr[1]),'Winsock Example',MB_OK + MB_ICONINFORMATION)
  end;

end;
end;
Mache ich prinzipiell etwas falsch.
Naja die Message kommt aber Weiterunten im Code richtig an habe ich gesehen mit dem Debugger.
meine frage Jetzt kann mir jemand helfen den Fehler zu finden?

DeddyH 11. Aug 2010 10:00

AW: Winsock Example Frage
 
Was denn jetzt? Zeigt nur die MessageBox Quatsch an, oder ist der auch im Debugger zu sehen?

[edit] Falls Ersteres, versuch es mal so (nur dahingetippt, mein Delphi kann kein Unicode):
Delphi-Quellcode:
if StrArr[0] = 'MSGBOX' then begin
   MessageBoxA(0,PAnsiChar(StrArr[1]),'Winsock Example',MB_OK or MB_ICONINFORMATION);
[/edit]

[edit2] Müsste das nicht eigentlich StrArr[0] sein? [/edit2]

CoYoTE 11. Aug 2010 10:44

AW: Winsock Example Frage
 
Die Messagebox zeigt Garnichts an nur im Debugger ist zusehen das die Nachricht als Fragezeichen ankommt nun
weiter unten im quelltext wird aufgeteilt in StrArr[0] und StrArr[1]
den die Message kommt vom Klienten so an.
MSGBOX|nachricht,

MSGBOX wird da in StrArr[0] Gespeichert und die Nachricht in StrArr[1]

Deshalb ist auch eine if abfrage den wen StrArr[0] MSGBOX ist dann wird die Message StrArr[1] Angezeigt nur da kommen wiegesagt Aber nur Fragezeichen an.
Der Client funktioniert aber richtig.
Der schickt die richtige Message die kommt ja au an wird aber in dem Server zu Fragezeichen.
An der besagten stelle.

Ohje hoffe ihr könnt mir helfen,

DeddyH 11. Aug 2010 10:50

AW: Winsock Example Frage
 
An welcher Stelle denn genau? Sieht "Data" noch plausibel aus, oder steht da bereits Müll drin?

CoYoTE 11. Aug 2010 10:53

AW: Winsock Example Frage
 
Zitat:

Zitat von CoYoTE (Beitrag 1041065)
Die Messagebox zeigt Garnichts an nur im Debugger ist zusehen das die Nachricht als Fragezeichen ankommt nun
weiter unten im quelltext wird aufgeteilt in StrArr[0] und StrArr[1]
den die Message kommt vom Klienten so an.
MSGBOX|nachricht,

MSGBOX wird da in StrArr[0] Gespeichert und die Nachricht in StrArr[1]

Deshalb ist auch eine if abfrage den wen StrArr[0] MSGBOX ist dann wird die Message StrArr[1] Angezeigt nur da kommen wiegesagt Aber nur Fragezeichen an.
Der Client funktioniert aber richtig.
Der schickt die richtige Message die kommt ja au an wird aber in dem Server zu Fragezeichen.
An der besagten stelle.

Ohje hoffe ihr könnt mir helfen,

An dieser Stelle kommt die Message richtig an und dann weis ich nicht weiter was falsch ist:

Delphi-Quellcode:
while ((iRecv > 0) and (iRecv <> INVALID_SOCKET)) do
      begin
        ReceiveData(hSocket, @Buffer);
        ZeroMemory(@Buffer, SizeOf(Buffer));
        iRecv := Recv(hSocket, Buffer, SizeOf(Buffer), 0);
      end;

DeddyH 11. Aug 2010 13:23

AW: Winsock Example Frage
 
Kannst Du den Code des Client mal anhängen?

CoYoTE 11. Aug 2010 13:55

AW: Winsock Example Frage
 
wäre es den hilfreich wen ich die Projekt Dateien auf mein Server uploade dann kannst es dir laden komplett???

hier der Client:
Delphi-Quellcode:
unit frmMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Menus, ComCtrls,Winsock, untListen, untClient;

type
  TForm4 = class(TForm)
    StatusBar1: TStatusBar;
    ListView1: TListView;
    PopupMenu1: TPopupMenu;
    Listen1: TMenuItem;
    Disconnect1: TMenuItem;
    SendMessage1: TMenuItem;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Disconnect1Click(Sender: TObject);
    procedure SendMessage1Click(Sender: TObject);
    procedure Listen1Click(Sender: TObject);
     procedure Status(Data: AnsiString);
private
  Listen: TListener;
     { Private declarations }
  public
  hServer: TSocket;
  intPort: Integer;
        { Public declarations }
  end;

var
  Form4: TForm4;

implementation

procedure TForm4.Disconnect1Click(Sender: TObject);
var
TmpClient:TClient;
begin
if assigned(ListView1.Selected) then begin
TmpClient:=ListView1.Selected.data;
TmpClient.ListItem:=ListView1.Selected;
TmpClient.RemoveClient;
end;
end;

procedure TForm4.FormCreate(Sender: TObject);
begin
listview1.Column[2].Width := 150;
end;

procedure TForm4.Listen1Click(Sender: TObject);
var
  wsaData: TWSAData;
  TmpStr:AnsiString;
  begin

  //Declare a port to listen on
  TmpStr:=InputBox('Listen port','Specify a port to open on for connections','12345');
  if trim(TmpStr) <> '' then
  begin
  IntPort:=StrToInt(TmpStr);

  //Initialize and create our socket to accept connections with
  WSAStartup($0202, wsaData);
  Listen := TListener.Create(True);
  with Listen do
  begin
    FreeOnTerminate := True;
    wPort := intPort;
    Resume;
  end;

end;
end;

procedure TForm4.SendMessage1Click(Sender: TObject);
Var
TmpClient:TClient;
TmpStr:AnsiString;
begin
if assigned(ListView1.Selected) then begin
TmpStr:=Inputbox('Send data to server','Specify message data to send','Hello from client');
if Trim(TmpStr) <> '' then begin

//Declare our client for sending data
TmpClient:=Listview1.selected.data;
TMPClient.ListItem:=Listview1.selected;
TmpClient.SendData('MSGBOX' + '|' + TmpStr);
end;
end;
end;

procedure TForm4.Status(Data: AnsiString);
begin
  //Output our status message data
  StatusBar1.Panels.Items[0].Text := 'Socket Status: ' + Data;
end;


{$R *.dfm}

end.
Da gibt es noch 2 weitere Units für den Client will hier Neds alles zuspammen mit so viel Code.
soll ich die posten???

DeddyH 11. Aug 2010 13:57

AW: Winsock Example Frage
 
Ich sagte ja: anhängen ;) Pack am besten das komplette Projekt in ein ZIP-Archiv.

CoYoTE 11. Aug 2010 14:03

AW: Winsock Example Frage
 
http://professorbass.eu/winsock.rar

DeddyH 11. Aug 2010 14:15

AW: Winsock Example Frage
 
Im Moment habe ich noch keine Idee, daher noch einmal die Frage: steht in der Variablen Data (Ereignis TServer.ReceiveData) bereits Müll, oder kommt das erst später? Ich habe den Verdacht, dass es an der Implementierung von Explode liegen könnte.

CoYoTE 11. Aug 2010 16:08

AW: Winsock Example Frage
 
Ja da steht schon Müll drinnen bei TServer.ReceiveData.

Und bei TServer.Connect
ReceiveData und ZeroMemory steht es richtig drinne im Buffer

das kann ich mit Sicherheit sagen!!!


Echt cool das sie mir helfen!!!

DeddyH 11. Aug 2010 16:34

AW: Winsock Example Frage
 
Ich muss leider zugeben, dass ich keine Ahnung habe, woran das liegen könnte (bzw. ich sehe es einfach nicht). Da muss mal jemand mit einem Delphi > 2007 ran, ich kann das ja auch nicht nachvollziehen mangels Unicode, sry.

CoYoTE 12. Aug 2010 01:39

AW: Winsock Example Frage
 
Ok
Danke für die Mühe ich hoffe es findet sich da jemand
das gibt es nicht oft Hilfe für umsonst.

Foren sind geil :-D


Also ich habe alles noch einmal genauer zusammengefasst das man nicht so viel blättern muss.

Folgendes Problem:
ich sende ein MSGBOX | Hallo , vom Client an den server.
es kommt hier noch richtig an:
Delphi-Quellcode:
procedure TServer.Connect;
  var
    Buffer: Array[0..8192] Of AnsiChar;
    iRecv: Integer;
  Begin
    if (WSAStartup($0202, wsaData) <> 0) then
    begin
   
      Writeln('Unable to start winsock, unable to continue');
      Readln;
   
      Exit;
    end;
    Close := False;
    repeat
   
      //Prepare a listen socket to be used for our connection
      //and declare its host/port information
      hSocket := Socket(AF_INET, SOCK_STREAM, 0);
      Addr.sin_family  := AF_INET;
      Addr.sin_port    := htons(hPort);
      Addr.sin_addr.S_addr := INET_ADDR(PAnsiChar(GetIPFromHost(hHost)));
   
      Writeln('Connecting to ' + GetIPFromHost(hHost));
   
      //Attempt the connection using our socket
      if (Winsock.Connect(hSocket, Addr, SizeOf(Addr)) = 0) then
      begin
   
        Writeln('Connected to host');
   
        //Notify our connected client of the connection and send
        //our information
        SendData('ADDNEW|' + UserName + '|' + CompName + '|' + 'Awaiting commands');
   
        //Attempt to receive data from our socket.
        ZeroMemory(@Buffer, SizeOf(Buffer));
        iRecv := Recv(hSocket, Buffer, SizeOf(Buffer), 0);
        while ((iRecv > 0) and (iRecv <> INVALID_SOCKET)) do    // <-----------Im Buffer ist alles ok
        begin
          ReceiveData(hSocket, @Buffer);     // <-----------Im Buffer ist alles ok
          ZeroMemory(@Buffer, SizeOf(Buffer));
          iRecv := Recv(hSocket, Buffer, SizeOf(Buffer), 0);
        end;
Und dann der Fehler wo ich nicht weis woran es liegt:
Delphi-Quellcode:
procedure TServer.ReceiveData(Socket: TSocket; Buffer: PByte);
  var
    Data: AnsiString;
    strArr: TDynStringArray;
  begin
   
    //Convert our data to a AnsiString and trim it
    Data := AnsiString(Buffer);
    Data := Trim(Data);   // <-----------Im Buffer Sind nurnoch Fragezeichen
   
    if Length(Data) > 0 then begin    // <-----------in Data Sind die Fragezeichen
   
    //Setup our dynamic array structure
    StrArr := Explode('|', Data);   // <-----------in Data Sind die Fragezeichen
   
    //Display incoming message (if strArr[0] = 'MSGBOX')
    if StrArr[0] = 'MSGBOX' then begin
     MessageBox(0,PChar(StrArr[1]),'Winsock Example',MB_OK + MB_ICONINFORMATION);
    end;
Und die Fragezeichen gehen so durch Explode durch und am ende bei ZeroMemory(@Buffer, SizeOf(Buffer)); ist die Nachricht wieder richtig zusehen im Buffer was ist da dazwischen was falsch ist???
das Ganze Projekt habe ich auf mein Server hochladen und ein paar Einträge von mir weiter hinten kann man sich es runterladen mit dem Client und alles was dazugehört.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:28 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz