Effettuare il PING: differenze tra le versioni

Da Gambas-it.org - Wikipedia.
Vai alla navigazione Vai alla ricerca
Nessun oggetto della modifica
Nessun oggetto della modifica
 
Riga 40: Riga 40:
  <FONT Color=gray>' ''int close(int _fd)''
  <FONT Color=gray>' ''int close(int _fd)''
  ' ''Close the file descriptor FD.''</font>
  ' ''Close the file descriptor FD.''</font>
  Private Extern close_C(_fd As Integer) As Integer In "libc:6" Exec "close"
  Private Extern close_C(_fd As Integer) As Integer Exec "close"
   
   
   
   

Versione attuale delle 04:30, 18 ott 2025

Per effettuare il PING (Packet INternet Groper ) con Gambas, si potrà lanciare l'omonimo comando bash "ping" seguito dal prefisso "www." più il nome del dominio oppure dall'indirizzo IP mediante le istruzioni Shell o Exec[].

In alternativa si potrà utilizzare il seguente codice che, usando alcune funzioni esterne, effettua una richiesta ICMP aprendo un socket.

Library "libc:6"

Private Enum IPPROTO_IP = 0, IPPROTO_ICMP, AF_INET, SOCK_DGRAM = 2, SOCK_RAW, IP_HDRINCL = 3, IPPROTO_TCP = 6

Public Struct SockAddr 
  SinFamily As Short
  SinPort As Short
  SinAddr As Pointer
End Struct

Public Struct timeval
  tv_sec As Long
  tv_usec As Long
End Struct

' int socket (int __domain, int __type, int __protocol)
' Create a new socket of type TYPE in domain DOMAIN, using protocol PROTOCOL.
Private Extern socket(__domain As Integer, __type As Integer, __protocol As Integer) As Integer

' int inet_pton (int __af, const char *__restrict __cp, void *__restrict __buf)
' Convert from presentation format of an Internet number in buffer starting at CP to the binary network format
' and store result for interface type AF in buffer starting at BUF.
Private Extern inet_pton(__af As Integer, __cp As String, __buf As Pointer) As Integer

' int gettimeofday (struct timeval *__restrict __tv, void *__restrict __tz)
' Get the current time of day, putting it into *TV.
Private Extern gettimeofday(__tv As Timeval, __tz As Pointer) As Integer

' ssize_t sendto (int __fd, const void *__buf, size_t __n, int __flags, __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
' Send N bytes of BUF on socket FD to peer at address ADDR (which is ADDR_LEN bytes long).
Private Extern sendto(__fd As Integer, __buf As Byte[], __n As Integer, __flags As Integer, __addr As SockAddr, __addr_len As Integer) As Long

' Read N bytes into BUF through socket FD.
' ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags, __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len)
Private Extern recvfrom(__fd As Integer, __buf As Byte[], __ As Long, __flags As Integer, __addr As Pointer, __addr_len As Pointer) As Long

' int close(int _fd)
' Close the file descriptor FD.
Private Extern close_C(_fd As Integer) As Integer Exec "close"


Public Sub Main()

 Dim sockfd, rc, buffer_len As Integer
 Dim aHeader As Byte[] = [8, 0, 0, 0, 0, 0, 0, 0]
 Dim iChecksum As Short
 Dim DestAddr As New SockAddr
 Dim buffer As New Byte[1024]
 Dim start_time, end_time As New Timeval

 sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)
 If sockfd < 0 Then
   Print "Errore di chiamata del socket: " & System.Error
   Quit 
 Endif

 DestAddr.SinFamily = AF_INET
 DestAddr.SinPort = 0
 DestAddr.SinAddr = Alloc(SizeOf(gb.Pointer), 2)

' Ad esempio, fa il PING al seguente indirizzo IP di un server DNS pubblico:
 rc = inet_pton(AF_INET, "84.200.70.40", DestAddr.SinAddr)
 If rc < 1 Then 
   Print "Errore nella conversione dell'indirizzo !"
   Quit 
 Endif

 iChecksum = CalcChecksum(aHeader)
 aHeader[2] = (iChecksum Lsr 8) And &HFF
 aHeader[3] = iChecksum And &HFF

 gettimeofday(start_time, 0)

' Cerca di risolvere in Gambas il "cast" fra le seguenti Strutture scritte in C « (struct sockaddr *)&dest_addr »:
 Dim p As Pointer = Alloc(Object.SizeOf(DestAddr), 1)
 Dim st As Stream
 st = Memory p For Write 
 Write #st, DestAddr.SinFamily As Short
 Write #st, 0 As Short
 Write #st, DestAddr.SinAddr, SizeOf(gb.Pointer) * 2
 st.Close

 rc = sendto(sockfd, aHeader, 8, 0, p, Object.SizeOf(DestAddr))
 If rc < 0 Then 
   Print "Errore invio:", System.Error
 Else 
   Print "Byte inviati:", rc
 Endif
 Free(p)
 Free(DestAddr.SinAddr)

 buffer_len = recvfrom(sockfd, buffer, buffer.Count, 0, 0, 0)
 If buffer_len < 0 Then Error.Raise("Errore !")

 gettimeofday(end_time, 0)

 Dim latenza As Float = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec) / 1000000.0
 Print "Latenza: ", latenza; " secondi"

 Finally 
   If sockfd Then 
     rc = close_C(sockfd)
   Endif
   If rc < 0 Then  'error
     Print "Errore di chiusura: " & System.Error
   Endif

   Catch 
     Debug Error.Text; " a "; Error.Where

End


Private Function CalcChecksum(aHeader As Byte[]) As Short

 Dim iSum As Long
 Dim iVal As Short

 For i As Integer = 0 To aHeader.Max Step 2
   iVal = (CShort(aHeader[i]) Lsl 8) + aHeader[i + 1]
   iSum += iVal
 Next

 While iSum > &HFFFF&
   iSum = (iSum Lsr 16) + (iSum And &HFFFF)
 Wend

 Return Not iSum

End

oppure si potrà utilizzare la funzione esterna di C "popen()", ad esempio come segue:

Library "libc:6"

' FILE *popen (const char *__command, const char *__modes)
' Create a new stream connected to a pipe running the given command.
Private Extern popen(__command As String, __modes As String) As Pointer

' size_t fread (void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream)
' Read chunks of generic data from STREAM.
Private Extern fread(__ptr As Pointer, __size As Long, __n As Long, __stream As Pointer) As Long


Public Sub ToggleButton1_Click()

 If ToggleButton1.Value Then
   Dim p1, p2 As Pointer
   Dim s As String
   p1 = Alloc(SizeOf(gb.Byte), 1)
   p2 = popen("ping www.gambas-it.org", "r")
   While ToggleButton1.Value
     Repeat
       fread(p1, 1, 1, p2)
       s &= String@(p1)
       Wait 0.001
     Until Right(s, 1) = "\n"
     ListBox1.Add(RTrim(s))
     s = Null
   Wend
 Else
   Free(p1)
   p1 = 0
 Endif

End


Public Sub Form_Close()

 Quit
  
End