Seite 4 von 5

Verfasst: 17.07.2007 01:40
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

Verfasst: 17.07.2007 09:14
von legion
Gute Lösung !
Funktioniert tadellos !

Lg. Legion

Verfasst: 17.07.2007 15:54
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.

Verfasst: 17.07.2007 18:00
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

Verfasst: 17.07.2007 18:09
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)

Verfasst: 17.07.2007 23:01
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

Verfasst: 18.07.2007 12:55
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

Verfasst: 18.07.2007 15:27
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.

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