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 »

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!
Benutzeravatar
N00B
Beiträge: 122
Registriert: 11.07.2007 22:28

Beitrag von N00B »

@DarkDragon & Sicro

Alle 3 Lösungen funzen :allright: und mir ist es egal welche schneller ist

:)

Wichtig ist nur, es funzt, und ich kann euch gar nicht genug Danken.

:praise: :praise: :praise: :praise:

Danke

Am liebsten würde ich euch dafür abknutchen :lol:
Benutzeravatar
N00B
Beiträge: 122
Registriert: 11.07.2007 22:28

Beitrag von N00B »

@Sicro,


Hi Sicro :-)

Der Code funzt wunderbar, um einen Timeout zu empfangen.

Aber wie soll ich damit Daten (http replies,404 not Found Replies usw empfangen ?

Oder wo müsste der Code zum empfangen stehen ?

Hab den Code hier von dir benutzt.
Sicro hat geschrieben:

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
Und schon paar Stunden rumprobiert gehabt, aber leider nicht hingekriegt :(
Benutzeravatar
Sicro
Beiträge: 964
Registriert: 11.08.2005 19:08
Kontaktdaten:

Beitrag von Sicro »

Hallöchen N00B,
Aber wie soll ich damit Daten (http replies,404 not Found Replies usw empfangen ?
Mit ReceiveNetworkData()

Meine Prozedur prüft über die WinAPI nur ob eine erfolgreiche Verbindung aufgebaut werden kann. Ist dies der Fall, wird die OpenNetworkConnection() von PB aufgerufen. Also kann der Rückgabewert (die ID) meiner Prozedur normal mit den PB-Funktionen weiterverwendet werden, als hättest du OpenNetworkConnection() anstatt OpenNetworkConnectionEx() genommen.

Mfg Sicro
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
N00B
Beiträge: 122
Registriert: 11.07.2007 22:28

Beitrag von N00B »

Sicro hat geschrieben:Hallöchen N00B,
Aber wie soll ich damit Daten (http replies,404 not Found Replies usw empfangen ?
Mit ReceiveNetworkData()

Meine Prozedur prüft über die WinAPI nur ob eine erfolgreiche Verbindung aufgebaut werden kann. Ist dies der Fall, wird die OpenNetworkConnection() von PB aufgerufen. Also kann der Rückgabewert (die ID) meiner Prozedur normal mit den PB-Funktionen weiterverwendet werden, als hättest du OpenNetworkConnection() anstatt OpenNetworkConnectionEx() genommen.

Mfg Sicro
Ja ich weiss das mit ReceiveNetworkData natürlich :)

Aber das Problem ist, ich weiss nicht was ID deiner Prozedur ist, und von welcher Prozdur muss ich die nehmen ? :(

Wo ist da die ID deiner Prozedur :oops: ?

Code: Alles auswählen

OpenNetworkConnectionEx(ServerName.s,Port.l,TimeOut.l,Type.l = #PB_Network_TCP)
Und irgendwann hatte ich mal halbwegs was hingekriegt, und dann kammen Meldungen "bla Exciplit can only blaabla"

Oder so :(

EDIT:

Hab den Übliche ReceiveNetworkData Style

Code: Alles auswählen

  *mem=AllocateMemory(2000)

  Repeat
    
    blub = ReceiveNetworkData(id, *mem, 2000) 
    
    If blub > 0
      zeuch.s=PeekS(*mem)
      Debug zeuch.s
    Else
      Debug "-.-"
    EndIf
    
    FreeMemory(*mem)
    *mem=AllocateMemory(2000)
    
  Until blub = 0
  CloseNetworkConnection(id)
an allen möglichen Stellen ausprobiert, aber es ist immer das Selbe Problem :(
With 'EnableExplicit', variables have to be declared: *mem
und wenn ich declare einsetzen will, kommt das Nächste Problem, daß nicht umgangen werden kann, so weit ich das verstanden hab.
A arocedure name needs to start with a character (a-z or _)
:(

Und das EnableExplicit am Anfang des Codes braucht man warscheinlich, sonst hättest es ja nicht reingemacht.
Benutzeravatar
Sicro
Beiträge: 964
Registriert: 11.08.2005 19:08
Kontaktdaten:

Beitrag von Sicro »

N00B hat geschrieben:ich weiss nicht was ID deiner Prozedur ist
Der Rückgabewert (ProcedureReturn) der Prozedur (Procedure) OpenNetworkConnectionEx() ist die ID.
N00B hat geschrieben:und von welcher Prozdur muss ich die nehmen ? :(
Öhm... gibt ja nur eine: OpenNetworkConnectionEx()
N00B hat geschrieben:With 'EnableExplicit', variables have to be declared: *mem

und wenn ich declare einsetzen will, kommt das Nächste Problem, daß nicht umgangen werden kann, so weit ich das verstanden hab.

Und das EnableExplicit am Anfang des Codes braucht man warscheinlich, sonst hättest es ja nicht reingemacht.
Der Befehl "EnableExplicit" teilt dem Compiler mit das er rummeckern soll, wenn eine Variable nicht "declared" ist.

So muss jede Variable mit Define, Protected, Static oder Global "declared" werden. Schreibt man im Code dann mal eine Variable durch schnelles Schreiben etwas verdreht, meckert der Compiler dann gleich rum, dass die Variable nicht "declared" ist.

Code: Alles auswählen

Text.s = "Hello World"
Debug Text
gibt "Hello World" aus.

Code: Alles auswählen

Text.s = "Hello World"
Debug Txet
gibt hingegen "0" zurück, weil der neuen Variable "Txet" vom Typ "Long" (Long wird standardmäßig genommen, wenn kein Typ (.b, .l, .q usw.) angegeben wird) kein Wert zugewiesen wurde. Wenn man hier ganz oben "EnabledExplicit" angegeben hätte, würde der Compiler meckern und nicht schweigend den falschen Code verarbeiten.

Der Befehl "EnabledExplicit" ist also keine Pflicht.


Hier ein Beispiel wie man den Header einer Internetseite ermitteln kann.

Code: Alles auswählen

InitNetwork()

#TimeOut = 1 ; in Sekunden

ID = OpenNetworkConnectionEx("www.purebasic.com",80,#TimeOut) 
If ID
  *Buffer = AllocateMemory(1024)
  
  ; Request senden
  Request.s = "HEAD / HTTP/1.0" + #CRLF$
  Request   + "Host: www.purebasic.com" + #CRLF$ + #CRLF$
  SendNetworkString(ID,Request)
  
  ; Auf Antwort warten
  While Not NetworkClientEvent(ID)
    Delay(100)
  Wend
  
  ; Antwort ermitteln und ausgeben
  ReceiveNetworkData(ID,*Buffer,MemorySize(*Buffer))
  MessageRequester("Antwort",PeekS(*Buffer))
  
  CloseNetworkConnection(ID)
Else
  MessageRequester("Fehler","Timeout oder Fehler")
EndIf
Mfg Sicro
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
N00B
Beiträge: 122
Registriert: 11.07.2007 22:28

Beitrag von N00B »

Ok jetzt geht´s :)

Danke für die Infos.

Hatte schon nenn Header usw, nur hab ich den Fehler gemacht nicht erst nenn Header zu verschicken sondern dachte ich könnte nach dem Opennetworkconnectionex gleich abchecken was reinkommt :D

Es funzt, soweit.

Gibt nur ein altes Prob, wofür du absolut nichts kannst.

ReceiveNetworkDate lässt sich nicht breaken, oder irgendwie zu einem Timeout Forcen, ausser von Win seinem internen Timeout.

Nehmen wir mal ne lahme japanische Site, oder nenn überlasteten Idle Proxy Server.

100 Bytes werden empfangen, und irgendwann nach 10 Sek wieder ein bisschen usw aber wenn jetzt 100Bytes ankommen würden, und dann 20 Sek gar nichts, erst dann lässt es der Befehl sein, ewig rumzuwarten.

Also kann es unter Umständen ewig so weitergehen, immer häpchenweise, 100 Byte, dann wird wieder 20 Sek gewartet usw :(
Benutzeravatar
Sicro
Beiträge: 964
Registriert: 11.08.2005 19:08
Kontaktdaten:

Beitrag von Sicro »

N00B hat geschrieben:Hatte schon nenn Header usw, nur hab ich den Fehler gemacht nicht erst nenn Header zu verschicken sondern dachte ich könnte nach dem Opennetworkconnectionex gleich abchecken was reinkommt :D
Nach dem Aufruf von OpenNetworkConnection(Ex) bekommst du bei HTTP von der Gegenstelle keine Daten zugesendet. Erst wenn du einen Request sendest, werden dir Daten gesendet.
N00B hat geschrieben:ReceiveNetworkDate lässt sich nicht breaken, oder irgendwie zu einem Timeout Forcen, ausser von Win seinem internen Timeout.
Dass ReceiveNetworkData() eine Wartepause einlegt, wenn zu dieser Zeit keine Daten zum Abholen vorhanden sind, konnte ich noch nicht nachvollziehen, da mir auf die Schnelle kein lahmer Server zur Verfügung stand.

Du solltest aber auf jeden Fall mit NetworkClientEvent() vor dem Aufruf von ReceiveNetworkData() prüfen, ob überhaupt Daten zum Auslesen vorhanden sind, damit nicht ins Leere gegriffen wird.

Mfg Sicro
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
lassma-asma
Beiträge: 107
Registriert: 10.07.2007 09:14
Wohnort: Saarland

Beitrag von lassma-asma »

@ DarkDragon & Sirco

Auch von mir nochmal ein großes Lob ! Genau das hab ich gebraucht im Moment ...

Echt super Coeds ...

Danke nochmal !

Gruß lassma-asma
Gruß lassma-asma

MultiPONG
HANGMAN


PB 3.94 und PureBasic 4.51 !!!
Antworten