OpenNetworkConnectionEx() mit Timeout

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Sicro
Beiträge: 964
Registriert: 11.08.2005 19:08
Kontaktdaten:

Beitrag von Sicro »

Ich habe hier auch noch eine Lösung gebastelt:

Code: Alles auswählen

InitNetwork()

Procedure OpenNetworkConnectionEx(ServerName.s,Port.l,TimeOut.l,Type.l = #PB_Network_TCP)
  Protected ID.l, Output.s

  #Flags = #PB_Program_Hide | #PB_Program_Open | #PB_Program_Read
 
  If Type = #PB_Network_TCP
    ID = RunProgram("ping","-w " + Str(TimeOut) + " -n 1 " + ServerName,"",#Flags)
    WaitProgram(ID)
    While AvailableProgramOutput(ID)
      Output + ReadProgramString(ID)
    Wend
    CloseProgram(ID)
  Else
    ProcedureReturn OpenNetworkConnection(ServerName,Port,#PB_Network_UDP)
  EndIf
 
  If Not FindString(Output,"berschreitung der Anforderung",1)
    ProcedureReturn OpenNetworkConnection(ServerName,Port,Type)
  Else
    ProcedureReturn -1
  EndIf
EndProcedure

Define ID.l = OpenNetworkConnectionEx("www.purebasic.com",80,5000)
If ID > 0
  Debug "Verbindung hergestellt"
  CloseNetworkConnection(ID)
Else
  Debug "TimeOut eingetreten"
EndIf
Mfg DerProgger
Zuletzt geändert von Sicro am 17.07.2007 17:37, insgesamt 1-mal geändert.
Benutzeravatar
legion
Beiträge: 467
Registriert: 08.10.2006 18:04
Computerausstattung: Intel Core i5-6500 @ 4x 3.6GHz mit Windows 10 Pro, Intel Core-i7 mit Ubuntu 18.04 bionic, x86_64 Linux 4.18.0-16-generic, Microsoft Surface Pro - Windows 10 Pro
Wohnort: Wien
Kontaktdaten:

Beitrag von legion »

Gute Lösung !
Funktioniert tadellos !

Lg. Legion
PB 5.71 LTS Windows 10 Pro & Ubuntu 18.04.2 LTS & Linux Mint 19.3
-----------------------------------------------------
Alles ist, wie man glaubt, dass es ist!
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

legion hat geschrieben:Gute Lösung !
Funktioniert tadellos !

Lg. Legion
Funktioniert nur seine? Ich finde seine nicht so toll wie meine. Immerhin benötigt seine Lösung das Programm "ping".

Außerdem hat er noch Type drin, obwohl es nur bei TCP sinn macht. Bei UDP wäre OpenNetworkConnection sowieso nach wenigen millisekunden durch.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
Sicro
Beiträge: 964
Registriert: 11.08.2005 19:08
Kontaktdaten:

Beitrag von Sicro »

Keine Sorge, bei mir hat dein Code ebenfalls prima geklappt. Nur gefällt mir das brutale Beenden des Threads (im Grunde wie KillThread()) nicht.

Zu deiner Kritik:
Stimmt, bei UDP ist es völlig sinnlos. Ich habe es ergänzt, danke :)
Das Ping-Programm habe ich verwendet, weil der Aufwand mit diesem geringer ist. Als nachteilig kann ich das nicht sehen, das hat doch bestimmt jeder auf seiner Windowskiste. Wem das trotzdem nicht gefällt, kann es ja direkt über die WinAPI machen.

Mfg DerProgger
Zuletzt geändert von Sicro am 17.07.2007 18:10, insgesamt 1-mal geändert.
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

DerProgger hat geschrieben:Das Ping-Programm habe ich verwendet, weil der Aufwand mit diesem geringer ist. Als nachteilig kann ich das nicht sehen, das hat doch bestimmt jeder auf seiner Windowskiste.
Ping empfängt aber doch auch nur ein Pong von der Serverseite von einem bestimmten Port (~53 wars doch). Auf jeden fall: Wenn der, der deine funktion benutzt auf den Server mit nem Port verbindet, den der Server gar nicht "offen" hat wirds kritisch, weil dann Pingt der ihn auf einem "offenen" Port und versucht auf einen "geschlossenen" Port zuzugreifen(Folglich: 20 sekunden timeout standard)
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
legion
Beiträge: 467
Registriert: 08.10.2006 18:04
Computerausstattung: Intel Core i5-6500 @ 4x 3.6GHz mit Windows 10 Pro, Intel Core-i7 mit Ubuntu 18.04 bionic, x86_64 Linux 4.18.0-16-generic, Microsoft Surface Pro - Windows 10 Pro
Wohnort: Wien
Kontaktdaten:

Beitrag von legion »

DarkDragon hat geschrieben: Funktioniert nur seine? Ich finde seine nicht so toll wie meine. Immerhin benötigt seine Lösung das Programm "ping".
Finde deine Lösung auch super !
Alle Wege führen nach Rom, einer über Wien, ein anderer über Tokio.
Habe nicht den ganzen Tread gelesen, entschuldige.

Lg. Legion
PB 5.71 LTS Windows 10 Pro & Ubuntu 18.04.2 LTS & Linux Mint 19.3
-----------------------------------------------------
Alles ist, wie man glaubt, dass es ist!
Benutzeravatar
Sicro
Beiträge: 964
Registriert: 11.08.2005 19:08
Kontaktdaten:

Beitrag von Sicro »

DarkDragon hat geschrieben:Wenn der, der deine funktion benutzt auf den Server mit nem Port verbindet, den der Server gar nicht "offen" hat wirds kritisch, weil dann Pingt der ihn auf einem "offenen" Port und versucht auf einen "geschlossenen" Port zuzugreifen(Folglich: 20 sekunden timeout standard)
Daran habe ich auch gedacht und dazu einen Test gemacht. Ergebnis: OpenNetworkConnection macht - jedenfalls bei mir - beim Verbinden zu einem geschlossenen Port nur eine Pause von einer Sekunde.

Mir ist bei meinem Code allerdings aufgefallen, dass manchmal ein Timeout gemeldet wird, obwohl eine Verbindung aufgebaut werden könnte. Bemerkbar wird dies vor allem beim mehrfachem Aufrufen. Ich werde später mal testen, ob das bei einem Ping direkt über die WinAPI ebenfalls noch so ist.

Des Weiteren habe schon versucht, den Verbindungstest über die WinAPI-Funktion "connect_()" durchzuführen, aber dort tritt ein Timeout ebenfalls erst nach ca. 20 Sekunden ein. Vielleicht wäre hier ein Non-Blocking-Socket die Lösung, aber wie man solch ein Socket erstellt, habe ich noch nicht herausgefunden.

Mfg DerProgger
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

DerProgger hat geschrieben:Vielleicht wäre hier ein Non-Blocking-Socket die Lösung, aber wie man solch ein Socket erstellt, habe ich noch nicht herausgefunden.

Mfg DerProgger
Genau das hat der Code von MLK bewirkt: Er erstellt einen Non blocking Socket und wartet auf einen Verbindungsaufbau. Eine WSA... Funktion gibts extra dafür. Unter Linux weiß ich es nicht.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
Sicro
Beiträge: 964
Registriert: 11.08.2005 19:08
Kontaktdaten:

Beitrag von Sicro »

So, ich habe nun einen weiteren Code geschrieben. Dieser versucht eine Verbindung zum Server direkt über die WinAPI herzustellen und beendet anschließend die Verbindung gleich wieder. Konnte die Verbindung erfolgreich hergestellt werden, wird die Verbindung erneut mit der PB-Funktion hergestellt.

Code: Alles auswählen

EnableExplicit

InitNetwork()

Procedure OpenNetworkConnectionEx(ServerName.s,Port.l,TimeOut.l,Type.l = #PB_Network_TCP)
  Protected WSAD.WSADATA, TV.TIMEVAL, Addr.SOCKADDR_IN, *HostInfo.HOSTENT, Write_FD.FD_SET
  Protected S.l, Switch.l, Retval.l, ServerIP.s
  
  TV\tv_sec = TimeOut
  Switch = #True
  
  If Type = #PB_Network_UDP
    ProcedureReturn OpenNetworkConnection(ServerName,Port,#PB_Network_UDP)
  EndIf
  
  If WSAStartup_($202,@WSAD)
    ProcedureReturn #False
  EndIf
  
  *HostInfo = gethostbyname_(@ServerName)
  If *HostInfo
    ServerIP = StrU(PeekB(PeekL(*HostInfo\h_addr_list)),0) + "."
    ServerIP + StrU(PeekB(PeekL(*HostInfo\h_addr_list) + 1),0) + "."
    ServerIP + StrU(PeekB(PeekL(*HostInfo\h_addr_list) + 2),0) + "."
    ServerIP + StrU(PeekB(PeekL(*HostInfo\h_addr_list) + 3),0)
  EndIf
  
  S = SOCKET_(#AF_INET,#SOCK_STREAM,#IPPROTO_TCP)
  If S = #SOCKET_ERROR
    WSACleanup_()
    ProcedureReturn #False
  EndIf
  
  ioctlsocket_(S,#FIONBIO,@Switch)
  
  With Addr
    \sin_addr = inet_addr_(ServerIP)
    \sin_port = htons_(Port)
    \sin_family = #AF_INET
  EndWith
  connect_(S,@Addr,SizeOf(Addr))
  
  With Write_FD
    \fd_count = 1
    \fd_array[0] = S
  EndWith
  Repeat
    Retval = select_(0,0,@Write_FD,0,@TV)
  Until Retval >= 0
  
  closesocket_(S)
  WSACleanup_()
  
  If Retval
    ProcedureReturn OpenNetworkConnection(ServerName,Port)
  EndIf
EndProcedure

#TimeOut = 1 ; in Sekunden
Define ID.l = OpenNetworkConnectionEx("www.purebasic.com",80,#TimeOut)
If ID
  Debug "Verbindung war erfolgreich"
  CloseNetworkConnection(ID)
Else
  Debug "Timeout oder Fehler"
EndIf
Mfg DerProgger
Benutzeravatar
legion
Beiträge: 467
Registriert: 08.10.2006 18:04
Computerausstattung: Intel Core i5-6500 @ 4x 3.6GHz mit Windows 10 Pro, Intel Core-i7 mit Ubuntu 18.04 bionic, x86_64 Linux 4.18.0-16-generic, Microsoft Surface Pro - Windows 10 Pro
Wohnort: Wien
Kontaktdaten:

Beitrag von legion »

Super ! Wird immer besser ! :lol:
Funktioniert auch unter Vista !

Lg. Legion
PB 5.71 LTS Windows 10 Pro & Ubuntu 18.04.2 LTS & Linux Mint 19.3
-----------------------------------------------------
Alles ist, wie man glaubt, dass es ist!
Antworten