Autor Beitrag
Peter18
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Di 31.03.15 16:09 
Ein freundliches Hallo an alle,

ich weiß, diese Frage habe ich bereits in einem anderen Thread gestellt, aber dort ist sie vielleicht etwas untergegangen. Daher stelle ich sie in einem neuen noch mal und hoffe auf einen Tipp.

In meiner Delphi 4 Version sind keine Objekte für Netzwerkanwendungen enthalten, aber die "winsock.pas". Ich brauche auch keine vollständige Netzwerk-Software. Ich möchte nur ein paar Informationen über Netzwerk mit einem anderen Rechner austauschen. Bei MS habe ich das Beispiel für einen Server gefunden und mit Delphi 4 programmiert (quick and dirty). Es geht auch alles gut bis "accept". Hier läuft er in die Wüste oder in einer Endlosschleife. Vielleicht ein falsch übergebener Parameter? Beim Aufruf von "CSock := accept( SSock, Nil, Nil );" kehrt die Kontrolle nicht zurück. Eine Absturzmeldung gibt es nicht.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
procedure TForm1.Button1Click(Sender: TObject);      // Verbinden
var
  VerR    : word;
  WSADATA : TWSAData;
  Res     : Integer;
  hints   : PAddrInfo;
  ARes    : PAddrInfo;

begin
  VerR := 2;
  Res := WSAStartup( VerR, WSADATA );
  if Res = 0 then
  begin
    hints             := AllocMem( SizeOf( TAddrInfo ) );
    ARes              := AllocMem( SizeOf( TAddrInfo ) );
    hints.ai_flags    := 0;
    hints.ai_family   := AF_INET;     // Internetprotokoll
    hints.ai_socktype := SOCK_STREAM;
    hints.ai_protocol := IPPROTO_TCP;
    hints.ai_flags    := AI_PASSIVE;

    // Resolve the server address and port
    Res := getaddrinfo(Nil, PChar( Edit2.Text ), hints, ARes );
    if Res = 0 then
    begin
      // Create a SOCKET for connecting to server
      SSock := socket( ARes.ai_family, ARes.ai_socktype, ARes.ai_protocol );
      if SSock <> INVALID_SOCKET then
      begin
        // Setup the TCP listening socket
        Res := bind( SSock, ARes.ai_addr^, ARes.ai_addrlen );
        if Res <> SOCKET_ERROR then
        begin
          freeaddrinfo( ARes );
          Res := listen( SSock, SOMAXCONN );
          if Res = 0 then
          begin
            // Accept a client socket
            CSock := accept( SSock, NilNil );    
            if CSock <> INVALID_SOCKET then
            begin
              // No longer need server socket
              closesocket( SSock );
              // Receive until the peer shuts down the connection

            end
            else
            begin
              Memo1.Lines.Add( 'Fehler Erstellen des Clientports: ' + IntToStr( WSAGetLastError ) );
              closesocket( SSock );
              WSACleanup;
            end;
          end
          else  // listen ServerSock
          begin
            Memo1.Lines.Add( 'Fehler Portprüfung: ' + IntToStr( WSAGetLastError ) );
            closesocket( SSock );
            WSACleanup;
          end;
        end
        else  // bind
        begin
          Memo1.Lines.Add( 'Fehler beim Binden: ' + IntToStr( WSAGetLastError ) );
          freeaddrinfo( ARes );
          closesocket( SSock );
          WSACleanup;
        end;
      end
      else    // socket
      begin
        Memo1.Lines.Add( 'Fehler beim Erstellen des Socket : ' + IntToStr( WSAGetLastError ) );
        freeaddrinfo( ARes );
        WSACleanup;
      end;
    end
    else      // getaddrinfo
    begin
      Memo1.Lines.Add( 'Fehler bei der Portprüfung: ' + IntToStr( Res ) );
      WSACleanup;
    end;
  end
  else        // WSAStartup
  begin
    Memo1.Lines.Add( 'Initialisierungsfehler: ' + IntToStr( Res ) );
  end;
end;


Ich habe irgentwie die Zeile "Res := bind( SSock, ARes.ai_addr^, ARes.ai_addrlen );" in verdacht.

Ich hoffe jemand hat einen Tipp.

Grüße von der sonnigen Nordsee

Peter
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 31.03.15 16:50 
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
... Hier läuft er in die Wüste oder in einer Endlosschleife. ... Ich habe irgentwie die Zeile "Res := bind( SSock, ARes.ai_addr^, ARes.ai_addrlen );" in verdacht.

Das kannst du doch einfach herausfinden, indem du durch diese Methode stepst – das nennt man Debuggen :wink:
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Di 31.03.15 17:22 
Hallo Perlsau,

selten so gelacht!!!
user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Das kannst du doch einfach herausfinden, indem du durch diese Methode stepst – das nennt man Debuggen :wink:

Es handelt sich nicht um eine Methode! Es ist eine Schnittstellenroutine der Winsock! Zwar kann ich in die CPU-Ansicht gehen, aber irgendwo geht es einfach nicht mehr weiter. Die Ursache ist nicht erkennbar.

Vielleicht hat aber jemand entsprechende Methoden (Objekte) und kann, per debug, nachsehen ob die Parameter rictig aufgesetzt sind, oder ob da noch etwas fehlt.

Grüße von der windigen Nordsee

Peter

Moderiert von user profile iconNarses: Komplettzitat des ersten Beitrags entfernt.
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1321
Erhaltene Danke: 117

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Di 31.03.15 17:34 
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
Beim Aufruf von "CSock := accept( SSock, Nil, Nil );" kehrt die Kontrolle nicht zurück. Eine Absturzmeldung gibt es nicht.


Schau Dir mal an was MS zu Accept schreibt, das ist das ganz normale Verhalten dieser Funktion.

Es wird solange gewartet bis ein Clientsocket daherkommt und mit dem Server eine Verbindung eingeht. Dann geht es in deinem Programmablauf weiter.
Das ist einer der Gründe warum man den Server in einen eigenen Thread packt anstatt ihn ihm Hauptthread auszuführen.

Dein Beispiel eigenet sich aber schön zum testen. Du brauchst jetzt nur ein zweites Programm (das mit dem Server ist ja blockiert) das den Client implementiert und via ButtonClick siehst Du dann wie der Server weitermacht wenn der Client sich verbindet.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 31.03.15 18:21 
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
Hallo Perlsau, selten so gelacht!!!

Warum klingst du dann so verägert, da du doch angeblich lachst?

user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Das kannst du doch einfach herausfinden, indem du durch diese Methode stepst – das nennt man Debuggen :wink:

Es handelt sich nicht um eine Methode! Es ist eine Schnittstellenroutine der Winsock! Zwar kann ich in die CPU-Ansicht gehen, aber irgendwo geht es einfach nicht mehr weiter. Die Ursache ist nicht erkennbar.


Du hattest aber doch geschrieben:

user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
... Ich habe irgentwie die Zeile "Res := bind( SSock, ARes.ai_addr^, ARes.ai_addrlen );" in verdacht.

Um den Verdacht zu bestätigen, stepst du dein Programm so lange durch, bis der Fehler auftritt. Tritt er an der von dir bezeichneten Stelle auf, dann wird der bloße Verdacht zur Gewißheit.

Tatsächlich befindet sich diese Zeile, die du unter Verdacht gestellt hattest, in einer Methode deines Form1-Objekts. Was gibt's da also zu meckern? Wenn du etwas anderes gemeint als geschrieben hast, darfst du nicht mich dafür verantwortlich machen :roll:


Zuletzt bearbeitet von Perlsau am Di 31.03.15 18:23, insgesamt 1-mal bearbeitet
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 01.04.15 11:59 
Hallo Sinspin,

vielen Dank für Deine Antwort! Ich habe so etwas schon vermutet, aber leider bei MS nicht gefunden. Die Beschreibung ist sehr kurz: "The accept function permits an incoming connection attempt on a socket." Falls Du eine genauere Beschreibung kennst, wäre ich für einen Link sehr dankbar. Vielleicht sind dort auch Infos zu anderen Routinen zu finden. Das Ganze soll später auch in einem Thread laufen und dient zunächst dazu, um den Einstieg zu finden.

Ich hatte den Server auf einem anderen Rechner im Netzwerk laufen, doch konnte keine Reaktion feststellen, als ich einen Client darauf losgelassen habe. Vielleicht ist da noch ein Fehler drin. Nochmals Dank, Du hast meine Vermutung bestätigt.

Hallo Perlsau,

Du wunderst Dich dass ich etwas vergrätzt bin?
user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
– das nennt man Debuggen :wink:
Wieso habe ich das Gefühl für dumm verkauft zu werden???
Leider habe ich ab und zu den Eindruck das einige wenige glauben andere von oben herab behandeln zu können oder Fragen nicht richtg lesen. Nicht nur in diesem Forum, in anderen sogar häufiger. Wer hier eine Frage stellt, dem sollte man unterstellen, dass er ein Problem hat. Natürlich gibt es auch Ausnahmen. Manchmal hat man sich so festgebissen, dass man den Wald vor lauter Bäumen nicht sieht. Nicht selten habe ich mich im Forum angemeldet, um eine Frage zu stellen und beim Formulieren der Frage fand ich selbst die Lösung. Leider klappt das nicht immer! Auch bei der Suche nach Informationen dreht man sich gern mal im Kreis und landet immer wider bei den selben Informationen.
Natürlich kommt es vor, dass ein "Unwissender" seine Frage so formuliert, dass ein "Wissender" nicht erkennt wo das Problem liegt. Dann müssen die Mißverständnisse im Dialog ausgeräumt werden, aber bitte auf Augenhöhe! Der "Unwissende" lernt auch daraus!

Aber zurück zu Deiner Antwort:
user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Tatsächlich befindet sich diese Zeile, die du unter Verdacht gestellt hattest, in einer Methode deines Form1-Objekts.
Selbstverständlich befindet sich der Aufruf dieser Funktion dort, aber sie ist Teil der Winsock! Dort kann ich nur auf Assemblerebene debuggen! Da ich schon mehrfach versucht habe auf dieser Ebene meine Parameter zu finden, aber keine schlüssigen Erkenntnisse gewinnen konnte, wie Delphi sie weitergibt, war ich mir nicht sicher, ob sie korrekt übergeben werden.

Vielleicht solltest Du auch mal über Deinen Fußtext nachdenken, wenn Du einen anderen Eindruck vermitteln möchtest.

Grüße von der noch immer windigen Nordsee

Peter

Für diesen Beitrag haben gedankt: Tastaro
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mi 01.04.15 13:36 
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
Du wunderst Dich dass ich etwas vergrätzt bin?

In der Tat! Etwas? Mir scheint, gewaltig. Kapier ich nicht wirklich. Wenn ich zu dumm bin, deinen Text zu verstehen, wieso ärgert dich das?

user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
Vielleicht solltest Du auch mal über Deinen Fußtext nachdenken, wenn Du einen anderen Eindruck vermitteln möchtest.

Mein Fußtext? Ich hab keinen Text auf meinem Fuß! Du meinst sicher meine Signatur. Hat die dich etwa vergrätzt? Aber stimmt, du hast recht, ich geb's ja ganz offen zu: Diese Signatur hab ich nur wegen dir, weil ich genau weiß, daß du dich darüber ärgerst. Ich bin halt ein schlimmer Finger, schlechte Gene, minderwertiger Abschaum eben, zu dumm zum Verstehen einfachster Texte (ist zum Glück alles noch nicht verboten). Hab ich kein Problem damit; es gibt zum Ausgleich ja auch wertvoll-intelligente Menschen wie dich, nicht wahr? Stell dir nur vor, alle wären so wertvoll wie du, würdest du dich da noch als was Besonderes fühlen können? Es muß auch Dumpfbacken wie mich geben, um den notwendigen Kontrast zu ermöglichen.

Nochmal: Du hattest von einem Verdacht geschrieben und eine Zeile benannt. Ein Verdacht ist keine Gewißheit. Um Gewißheit zu erlangen, benutzt man den Debugger. Was ist daran falsch? Daß du dir in Wirklichkeit sicher warst, daß der Aufruf in dieser Zeile das Problem darstellt? Geschrieben hast du aber was anderes. Und nun darfst du dich gerne weiterärgern, wenn du meinst, daß dir das was bringt. Mir ist es wurscht.

Aber lassen wir das, du hast da was in den falschen Hals gekriegt und machst mich dafür verantwortlich. Keine Ahnung, welchen Eindruck du damit machen wolltest ...
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 01.04.15 13:48 
Ein freundliches Hallo an alle,

hier ein Update: Der Client läuft bis "Res := connect( CSock, ARes.ai_addr^, ARes.ai_addrlen );" und gibt -1 zurück. In Edit1.Text steht der jeweilige Servername, in Edit2.Text die Portnummer "27015". Nachdem ich den Server gestartet habe wird der Client auf einem anderen gestartet.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
procedure TForm1.Button1Click(Sender: TObject);      // Verbinden
var
  VerR    : word;
  WSADATA : TWSAData;
  Res     : Integer;
  hints   : PAddrInfo;
  ARes    : PAddrInfo;

begin
  VerR := 2;
  Res := WSAStartup( VerR, WSADATA );
  if Res = 0 then
  begin
    hints             := AllocMem( SizeOf( TAddrInfo ) );
    hints.ai_flags    := 0;
    hints.ai_family   := AF_UNSPEC;
    hints.ai_socktype := SOCK_STREAM;
    hints.ai_protocol := IPPROTO_TCP;

    // Resolve the server address and port
    Res := getaddrinfo( PChar( Edit1.Text ), PChar( Edit2.Text ), hints, ARes );
    if Res = 0 then      //(EAI_AGAIN)
    begin
      Memo1.Lines.Add( 'socket' );
      CSock := socket( ARes.ai_family, ARes.ai_socktype, ARes.ai_protocol );
      if CSock <> INVALID_SOCKET then
      begin
        Memo1.Lines.Add( 'connect' );
        Res := connect( CSock, ARes.ai_addr^, ARes.ai_addrlen );
        Memo1.Lines.Add( 'connect: ' + IntToStr( Res ) );
        if Res <> SOCKET_ERROR then
        begin
          Connected := true;
          freeaddrinfo( ARes );
        end
        else  // connect
        begin
          Memo1.Lines.Add( 'Fehler bei connect: ' + IntToStr( Res ) );
          closesocket( CSock );
          freeaddrinfo( ARes );
        end;
      end
      else    // Socket
      begin
        Memo1.Lines.Add( 'Fehler bei socket: ' + IntToStr( WSAGetLastError ) );
        freeaddrinfo( ARes );
        WSACleanup;
      end;
      //freeaddrinfo( ARes );
      if CSock = INVALID_SOCKET then WSACleanup;
    end;
    FreeMem( hints );
    //FreeMem( ARes  );
  end
  else        // getaddrinfo
  begin
    Memo1.Lines.Add( 'Fehler bei WSAStartup: ' + IntToStr( Res ) );
    WSACleanup;
  end;
end;


Ich hoffe auf einen Tipp.

Grüße von der Nordsee

Peter
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 01.04.15 13:50 
Hallo Perlsau,

siehe oben, Antwort überflüssig!
Tastaro
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 414
Erhaltene Danke: 23



BeitragVerfasst: Mi 01.04.15 14:07 
Ermittelt getaddrinfo die richtige IP-Adresse?
Firewall auf dem Rechner mit dem Server?

Bei mir sieht die connect-Routine so aus:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
function to_tcpip_client_socket.connect(strIp: string; iPort: integer): integer;
var
  recSocketAddress: tsockaddrin;
   pcIp: pchar;
begin
   disconnect;

   recSocketAddress.sin_family := PF_INET;
   recSocketAddress.sin_port := htons(iPort);
   pcIp := pchar(strIp);
   recSocketAddress.sin_addr.S_addr := inet_addr(pcIp);

   iSocketHandle := winsock.socket(AF_INET, SOCK_STREAM, 0); 

   if (iSocketHandle <> INVALID_SOCKET) then
   begin
      if winsock.connect(iSocketHandle, recSocketAddress, sizeof(recSocketAddress)) = 0 then
         Result := 0
      else
      begin
         Result := winsock.wsagetlasterror;
         winsock.closesocket(iSocketHandle);
         iSocketHandle := INVALID_SOCKET;
      end;
   end
   else
      Result := winsock.wsagetlasterror;
   boConnected := (Result = 0);
   if boConnected then
   begin
      strRemoteIp := strIp;
      iRemotePort := iPort;
      oClientThread := to_tcpip_client_thread.create(iSocketHandle,
                          iReceiveBufferSize_bytes);
      oClientThread.yOnDisconnect := on_disconnect;
      oClientThread.yOnError := on_error;
      oClientThread.yOnDataReceived := on_data_received;
      oClientThread.resume;
   end;
end;
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1321
Erhaltene Danke: 117

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Mi 01.04.15 14:27 
Hallo Peter,

Microsoft ist in Sachen API Dokumentation wirklich brauchbar. Das einzige was man machen muss, ist sich durch alle verwendeten Befehle zu graben und auch den angegebenen Links mal zu folgen. In deinem Fall bin ich nicht bei Accept fündig geworden, sondern bei Listen. Gesucht habe ich via goggel nach "MSDN socket accept", dann ist es gleich der erste Treffer.

Edith:
Starte mal Server und Client auf dem gleichen Rechner. So kannst du erstmal noch ein paar Fehlerquellen ausschließen.

Peter, sei so nett und ignorier einfach die kindischen Spielchen, ich bin mir sicher Du stehst da deutlich drüber. Unsere perl sau ist halt noch jung und sucht immer mal nach Gelegenheiten mit älteren seine Kräfte zu messen.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?

Für diesen Beitrag haben gedankt: Peter18
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 01.04.15 14:36 
Hallo Tastaro,

Dank für Deine Antwort. Inzwischen bin auch ich auf die Brandmauer gekommen und siehe da, Ausname eintragen und es klappt! Die Funktionen "htons" und "inet_addr" habe ich nicht verwendet, weil sie im Beispiel von MS nicht vorgegeben waren. Die Namensauflösung soll laut Beschreibung in "getaddrinfo" erfolgen. Da sie in der "winsock.pas" meiner Version nicht enthalten war, habe ich sie entsprechend deklariert. Ein Objekt "Winsock" muß ich mir erst noch stricken.

Werd mir Deine Lösung aber noch genauer ansehen. Danke!

Grüße von der momentan sonnigen aber noch sehr windigen Nordsee

Peter
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 01.04.15 14:52 
Hallo Stefan,

Danke für Deine Antwort, auch für die "perl sau". Schade nur, dass er nicht lesen kann.

Der Tipp mit "Listen" scheint gut zu sein. Unter "Remarks" steht einiges an Text.

Ich hatte auch überlegt, ob ich auf einem Rechner testen sollte, war mir aber nicht sicher, ob ich ohne zusätzliche Funktionsaufrufe einen Port mehrfach benutzen kann.

Grüße von der Nordsee

Peter
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mi 01.04.15 15:20 
Da haben sich nun also zwei zusammengetan zum gemeinsamen Provozieren. Sehr unreifes Verhalten, finde ich. Möchtet ihr euch gerne dem Admin erklären oder hört das jetzt auf?