Effettuare il PING
Vai alla navigazione
Vai alla ricerca
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 In "libc:6" 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)
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