Seite 4 von 5

Verfasst: 18.07.2007 18:42
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

Verfasst: 18.07.2007 22:56
von legion
Super ! Wird immer besser ! :lol:
Funktioniert auch unter Vista !

Lg. Legion

Verfasst: 04.11.2007 17:15
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:

Verfasst: 07.01.2008 22:36
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 :(

Verfasst: 12.01.2008 00:58
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

Verfasst: 24.01.2008 21:46
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.

Verfasst: 26.01.2008 19:19
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

Verfasst: 31.01.2008 19:25
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 :(

Verfasst: 02.02.2008 22:35
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

Verfasst: 03.02.2008 12:15
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