Results 1 to 14 of 14

Thread: IcmpSendEcho2 with APC call back

  1. #1

    Thread Starter
    Member
    Join Date
    Jun 2013
    Posts
    43

    IcmpSendEcho2 with APC call back

    Hi Guys, I am using this API call extensively but I need to measure sub millisecond icmp responses. The only way I can think of doing that is to utilize the option of an APC callbck and measure the time when I get called back. Unfortunately I don't understand how to pass the APC parameters to IcmpSendEcho2. Anyone have an experience of using APC callbacks in VB?

    thanks

  2. #2
    Addicted Member
    Join Date
    Feb 2014
    Location
    USA
    Posts
    128

    Re: IcmpSendEcho2 with APC call back

    You're in luck. I've been using this method for a while and been meaning to create a nice demo of it to add to the CodeBank here, but just been too busy with other stuff. I needed this also a while back and couldn't find any examples on the Interwebs, so I paid someone more competent to help make it work. It's really simple actually.

    So here's the call for a single ping:

    nRet = IcmpSendEcho2(hPort, _
    0&, _
    AddressOf ApcRoutine, _
    ApcContext, _
    dwAddress, _
    RequestData, _
    Len(RequestData), _
    0&, _
    VarPtr(IcmpBufferReply), _
    LenB(IcmpBufferReply), _
    Timeout)

    Notice the AddressOf operator pointing to ApcRoutine(), though you can call it anything you want, obviously.

    This is what the callback routine looks like:
    Public Function ApcRoutine(ByVal ApcContext As Long, ByVal lpIOStatusBlock As Long, ByVal Reserved As Long) As Long

    You then use SleepEx() with the Alertable option set to true (in a repeating timer for example) and if the kernel has one or more pings ready or you, SleepEx will force the ApcRoutine() to fire, similar to what WaitForSingleObject does in other IcmpSendEcho2 examples you've seen that use event arrays. Except in this case, if there are 10 ping replies, calling will fire the callback routine 10 times, one for each ping reply. If there are no ping replies, SleepEx will just sleep for that amount of time. You can use 0ms for the wait time if you'd like. I like the APC method better because there's no need for Event variable Long arrays, etc. It makes for the absolute fastest ping sweep possible. I use this heavily in my own software. I hope that helps!

    One thing though, AFAIK, this will NOT allow you to do any sub-millisecond measurements. I'm not sure if Windows IcmpSendEcho2() has that ability.

  3. #3
    PowerPoster
    Join Date
    Dec 2004
    Posts
    25,618

    Re: IcmpSendEcho2 with APC call back

    i have a sample that i downloaded from somewhere, uses gettickcount to time each ping

    class
    Code:
    Option Explicit
    
    
    
    Private Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As Long
        bInheritHandle As Long
    End Type
    
    Private Type ip_option_information
        ttl             As Byte 'Byte     'Time To Live
        Tos             As Byte     'Type Of Service
        Flags           As Byte     'IP header flags
        OptionsSize     As Byte     'Size in bytes of options data
        OptionsData     As Long     'Pointer to options data
    End Type
    
    Private Type ICMP_ECHO_REPLY
        Address         As Long
        Status          As Long
        RoundTripTime   As Long
        datasize        As Long 'formerly integer
       'Reserved        As Integer
        DataPointer     As Long
        Options         As ip_option_information
        Data            As String * 250
    End Type
    
    Private Declare Function IcmpCreateFile Lib "icmp.dll" () As Long
    Private Declare Function IcmpCloseHandle Lib "icmp.dll" (ByVal IcmpHandle As Long) As Long
    Private Declare Function inet_addr Lib "wsock32" (ByVal s As String) As Long
    
    Private Declare Function IcmpSendEcho2 Lib "icmp.dll" (ByVal IcmpHandle As Long, ByVal hEvent As Long, ByVal ApcRoutine As Any, ByVal ApcContext As Long, ByVal DestinationAddress As Long, ByVal RequestData As String, ByVal RequestSize As Long, ByVal RequestOptions As Long, ByVal ReplyBuffer As Long, ByVal ReplySize As Long, ByVal TimeOut As Long) As Long
    
    Private Declare Function CreateEvent Lib "kernel32" Alias "CreateEventA" (lpEventAttributes As SECURITY_ATTRIBUTES, ByVal bManualReset As Long, ByVal bInitialState As Long, ByVal lpName As String) As Long
    'Private Declare Function WaitForMultipleObjects Lib "kernel32" (ByVal nCount As Long, lpHandles As Long, ByVal bWaitAll As Long, ByVal dwMilliseconds As Long) As Long
    'Private Declare Function WaitForMultipleObjectsArray Lib "kernel32" Alias "WaitForMultipleObjects" (ByVal nCount As Long, lpHandles() As Long, ByVal bWaitAll As Long, ByVal dwMilliseconds As Long) As Long
    Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
    
    
    Private Declare Function ResetEvent Lib "kernel32" (ByVal hEvent As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    
    
    Private Const WAIT_OBJECT_0 As Long = 0
    Private Const WAIT_TIMEOUT As Long = &H102
    Private Const WAIT_ABANDONED = &H80
    Private Const WAIT_FAILED = -1&
    Private Declare Function GetTickCount Lib "kernel32" () As Long
    
    Public Event PingSuccess(sIPAdress As String, lNewStatus As Long, ArrayIndex As Long)
    Public Event PingFail(sIPAdress As String, lNewStatus As Long, ArrayIndex As Long)
    
    Private mvarNumParalellActions As Long
    Private mvarListPingRunning As Boolean
    
    Public Property Let NumParalellActions(ByVal NewData As Long)
        mvarNumParalellActions = NewData
    End Property
    Public Property Get NumParalellActions() As Long
        NumParalellActions = mvarNumParalellActions
    End Property
    
    Public Property Get ListPingRunning() As Boolean
        ListPingRunning = mvarListPingRunning
    End Property
    
    Public Function PingHostSingle(sHostIP As String, TimeOut As Long) As Long
    Const sSendData As String = "TESTMESSAGE"
    Dim Buffer As ICMP_ECHO_REPLY
    Dim lhwndPort As Long
    Dim hEvent As Long
    Dim sd As SECURITY_ATTRIBUTES
    Dim WaitRes As Long
    Dim tm1 As Long, tm2 As Long
    
        '//needed for Create Event
        With sd
            .nLength = Len(sd) 'we pass the length of sd
            .lpSecurityDescriptor = 0
            .bInheritHandle = 0
        End With
    
        '//We create an Event-ID to be registered with IcmpSendEcho2 and WaitForMultipleObjects to wait for
        hEvent = CreateEvent(sd, True, False, "PINGV2")
    
        lhwndPort = IcmpCreateFile()    '//Standard for ICMP, create a handle
        
        Call IcmpSendEcho2(lhwndPort, hEvent, Nothing, 0, inet_addr(sHostIP), sSendData, Len(sSendData), 0, VarPtr(Buffer), Len(Buffer), 1000)
    
        '//Gere we start to wait
        tm1 = GetTickCount()
        Do
            WaitRes = WaitForSingleObject(hEvent, 5) ' WaitForMultipleObjects(1, hEvent, 1, 10)
            tm2 = GetTickCount
            DoEvents
            If (tm2 - tm1) < 1000 Then
                Select Case WaitRes
                    Case WAIT_ABANDONED, WAIT_FAILED
                        DoEvents
                        PingHostSingle = -2
                        Exit Do
                    Case WAIT_OBJECT_0
                        If Buffer.Status = 0 Then
                            PingHostSingle = Buffer.RoundTripTime
                        Else
                            PingHostSingle = -1
                        End If
                        Exit Do
    '//Cause were in a loop, this message will not work for us
    '                Case WAIT_TIMEOUT
                End Select
                DoEvents
            Else
                DoEvents
                PingHostSingle = -1
                Exit Do
            End If
        Loop While (1)
        '//And clear all created things
        ResetEvent hEvent
        IcmpCloseHandle lhwndPort
    End Function
    
    
    Public Function PingHostList(saIpAdresses() As String, TimeOutHost As Long, TimeOutAll As Long) As Boolean
    Dim NumAdresses As Long
    Dim laHandlesICMP() As Long
    Dim laEvents() As Long
    Dim laTimerStart() As Long
    Dim laTimerSop() As Long
    Dim laWaitResults() As Long
    Dim bUseResult() As Boolean
    Dim baEchoSend() As Boolean
    Dim aBuffers() As ICMP_ECHO_REPLY
    Dim bProcessed() As Integer
    Dim nProcessed As Long
    Dim nLoop As Long
    Dim baInitiated() As Boolean
    Dim TimerStart As Long
    Dim Timerstop As Long
    
    Dim Buffer As ICMP_ECHO_REPLY
    Dim sd As SECURITY_ATTRIBUTES
    Const sSendData As String = "PINGDATAMESSAGE"
    Dim WaitRes As Long
    
    Dim nStart As Long, nEnd As Long, BoundCtr As Long
    
        '//Prevent from reentry
        If mvarListPingRunning = True Then
            PingHostList = False
            Exit Function
        End If
        mvarListPingRunning = True
        NumAdresses = UBound(saIpAdresses)
    '//init the needed arrays
        ReDim laHandlesICMP(NumAdresses)
        ReDim laEvents(NumAdresses)
        ReDim laTimerStart(NumAdresses)
        ReDim laTimerSop(NumAdresses)
        ReDim laWaitResults(NumAdresses)
        ReDim baEchoSend(NumAdresses)
        ReDim aBuffers(NumAdresses)
        ReDim bProcessed(NumAdresses)
        
        '//needed for Create Event
        With sd
            .nLength = Len(sd) 'we pass the length of sd
            .lpSecurityDescriptor = 0
            .bInheritHandle = 0
        End With
        
        For nLoop = 0 To NumAdresses - 1
            '//We create an Event for WaitForMultipleObjects to wait for
            laEvents(nLoop) = CreateEvent(sd, True, False, "PINGV2C" & nLoop)
            laHandlesICMP(nLoop) = IcmpCreateFile()    '//Standard for ICMP
        Next
        TimerStart = GetTickCount
        nProcessed = 0  '//Reset Counter for processed hosts
        nStart = 0
        If NumAdresses > mvarNumParalellActions Then
            nEnd = mvarNumParalellActions
        Else
            nEnd = NumAdresses - 1
        End If
        BoundCtr = 0
        Do
            For nLoop = nStart To nEnd
                '//Did we already request an echo
                If baEchoSend(nLoop) = False Then
                    baEchoSend(nLoop) = True    '//Lock this adress, so we don't create a second Ping
                    Call IcmpSendEcho2(laHandlesICMP(nLoop), laEvents(nLoop), Nothing, 0, inet_addr(saIpAdresses(nLoop)), sSendData, Len(sSendData), 0, VarPtr(aBuffers(nLoop)), Len(aBuffers(nLoop)), TimeOutHost)
                End If
                If bProcessed(nLoop) = False Then
                    laWaitResults(nLoop) = WaitForSingleObject(laEvents(nLoop), 5) '//We wait only for 5 Millisecs, to give all the other IPs Time to answer
                    Select Case laWaitResults(nLoop)
                        Case WAIT_ABANDONED, WAIT_FAILED
                            DoEvents
                            bProcessed(nLoop) = -1
                            nProcessed = nProcessed + 1
                            BoundCtr = BoundCtr + 1
                        Case WAIT_OBJECT_0
                            bProcessed(nLoop) = 1
                            nProcessed = nProcessed + 1
                            BoundCtr = BoundCtr + 1
                            If aBuffers(nLoop).Status = 0 Then
                                '//Valid Info : So Host is reachable
                                RaiseEvent PingSuccess(saIpAdresses(nLoop), aBuffers(nLoop).RoundTripTime, nLoop)
                            Else
                                RaiseEvent PingFail(saIpAdresses(nLoop), -1, nLoop)
                            End If
        '//Cause were in a loop, this message will not work for us
    '                    Case WAIT_TIMEOUT
                            'bProcessed(nLoop) = -1
                    End Select
                    End If
                    DoEvents
                Next
            Timerstop = GetTickCount
            If (Timerstop - TimerStart) < TimeOutAll Then
                '
            Else
                DoEvents
                Debug.Print "TIMED OUT"
                Exit Do
            End If
            '//All done, no more Action needed
            If nProcessed >= NumAdresses - 1 Then
                Exit Do
            End If
            If nEnd < NumAdresses And BoundCtr >= mvarNumParalellActions Then
                nStart = nEnd + 1
                nEnd = nEnd + mvarNumParalellActions
                If nEnd > NumAdresses - 1 Then nEnd = NumAdresses - 1
                BoundCtr = 0
                Debug.Print "New bounds :"; nStart, nEnd, Time
            End If
        Loop While (1)
            
    '//IMPORTANT : UNregister all messages/Evemnts and open ICMP-handles
        For nLoop = 0 To NumAdresses - 1
            ResetEvent laEvents(nLoop)
            IcmpCloseHandle (laHandlesICMP(nLoop))
            If bProcessed(nLoop) <= 0 Then
                '//notify caller with the rest of the host, that we haven't hit
                RaiseEvent PingFail(saIpAdresses(nLoop), -1, nLoop)
            End If
        Next
    '//And we free up some memory
        Erase laHandlesICMP
        Erase laEvents
        Erase laTimerStart
        Erase laTimerSop
        Erase laWaitResults
        Erase baEchoSend
        Erase aBuffers
        Erase bProcessed
        mvarListPingRunning = False
    End Function
    
    
    Private Sub Class_Initialize()
        mvarNumParalellActions = 500
    End Sub
    form
    Code:
    Option Explicit
    Private Declare Function GetTickCount Lib "kernel32" () As Long
    Private WithEvents m_clsPingBase As ClassPingBase
    
    Private m_bFirstRun As Boolean
    
    Private Sub btnPing_Click()
    Dim res As Long
        btnPing.Enabled = False
        res = m_clsPingBase.PingHostSingle(txtIP, 100)
        If res < 0 Then
            lblPResult.Caption = ""
            lblPResult.BackColor = vbRed
        Else
            lblPResult.Caption = res
            lblPResult.BackColor = vbGreen
            
        End If
        btnPing.Enabled = True
    End Sub
    
    Private Sub btnPingAsync_Click()
    Dim saAdresses() As String, n As Integer
    Dim tm1 As Long, tm2 As Long, mystr As String
        
        btnPingAsync.Enabled = False
        ReDim saAdresses(LV_IPs.ListItems.Count)
        For n = 1 To LV_IPs.ListItems.Count
            '//Store value
            If LV_IPs.ListItems(n).SubItems(1) = "---" Then
                LV_IPs.ListItems(n).ListSubItems(1).Tag = -1
            Else
                If Len(LV_IPs.ListItems(n).SubItems(1)) Then
                    LV_IPs.ListItems(n).ListSubItems(1).Tag = LV_IPs.ListItems(n).ListSubItems(1).Text
                End If
            End If
            LV_IPs.ListItems(n).SubItems(1) = ""
            saAdresses(n - 1) = LV_IPs.ListItems(n).Text
        Next
        tm1 = GetTickCount()
        m_clsPingBase.NumParalellActions = 1000
        m_clsPingBase.PingHostList saAdresses, 100, (LV_IPs.ListItems.Count * 100) / 2
        btnPingAsync.Enabled = True
        tm2 = GetTickCount()
        m_bFirstRun = True
        Dim w, ns
        Set w = CreateObject("wscript.shell")
        For n = 1 To LV_IPs.ListItems.Count
        
        If Not LV_IPs.ListItems(n).SubItems(1) = "---" Then
            Set ns = w.exec("nslookup " & LV_IPs.ListItems(n))
            
            mystr = mystr & LV_IPs.ListItems(n) & vbTab & Replace(ns.stdout.readall, vbNewLine, vbTab) & vbNewLine
        End If
        Next
        
        Open App.Path & "\pinged.txt" For Output As 1
        Print #1, mystr
        Close 1
    '    MsgBox Format((tm2 - tm1) / 1000, "0.00") & " secs", , "Time needed"
    End Sub
    
    Private Sub btnPingList_Click()
    Dim n As Long, res As Long
    Dim tm1 As Long, tm2 As Long
        tm1 = GetTickCount()
        btnPingList.Enabled = False
        For n = 1 To LV_IPs.ListItems.Count
            LV_IPs.ListItems(n).Selected = True
            LV_IPs.ListItems(n).EnsureVisible
            res = m_clsPingBase.PingHostSingle(LV_IPs.ListItems(n).Text, 100)
            If res < 0 Then
                LV_IPs.ListItems(n).SubItems(1) = "---"
            Else
                LV_IPs.ListItems(n).SubItems(1) = res
            End If
        Next
        btnPingList.Enabled = True
        tm2 = GetTickCount()
        MsgBox Format((tm2 - tm1) / 1000, "0.00") & " secs", , "Time needed"
    End Sub
    
    Private Sub Form_Load()
    Dim n As Integer, m As Integer, k As Integer
    Dim lfd As Long, sreturn As String
    Dim sxIPfrom() As String, sxIPTo() As String
    Dim i1 As Integer, i2 As Integer, i3 As Integer, i4 As Integer, sData As String
    Dim BoundsL() As Integer, BoundsH() As Integer
        lblPResult.Caption = ""
        m_bFirstRun = False
    '    For m = 1 To 15
    '        For n = 1 To 255
    '            LV_IPs.ListItems.Add , , "10.49." & m & "." & n
    '        Next
    '    Next
    
        lfd = FreeFile
        Open App.Path & "\iplist.txt" For Input As #lfd
            Do While Not EOF(lfd)
                Line Input #lfd, sreturn
                If Len(sreturn) Then
                    If Left(sreturn, 1) <> "#" Then
                        k = InStr(sreturn, "-")
                        m = InStr(sreturn, ":")
                        If k Then   '//Komplete network
                            sxIPfrom = Split(Left(sreturn, k - 1), ".")
                            sxIPTo = Split(Mid(sreturn, k + 1), ".")
                            ReDim Preserve sxIPfrom(3)
                            ReDim Preserve sxIPTo(3)
                            ReDim BoundsH(3)
                            ReDim BoundsL(3)
                            For n = 0 To 3
                                BoundsL(n) = Val(sxIPfrom(n))
                                If BoundsL(n) > 255 Then BoundsL(n) = 255
                                BoundsH(n) = Val(sxIPTo(n))
                                If BoundsH(n) > 255 Then BoundsH(n) = 255
                            Next
                            For i1 = BoundsL(0) To BoundsH(0)
                                For i2 = BoundsL(1) To BoundsH(1)
                                    For i3 = BoundsL(2) To BoundsH(2)
                                        For i4 = BoundsL(3) To BoundsH(3)
                                            sData = i1 & "." & i2 & "." & i3 & "." & i4
                                            LV_IPs.ListItems.Add , , sData
                                        Next
                                    Next
                                Next
                            Next
                        ElseIf m Then
                            sxIPfrom = Split(Left(sreturn, m - 1), ".")   '//The Base adress
                            ReDim Preserve sxIPfrom(2)
                            sxIPTo = Split(Mid(sreturn, m + 1), ",")
                            For n = 0 To UBound(sxIPTo)
                                sData = sxIPfrom(0) & "." & sxIPfrom(1) & "." & sxIPfrom(2) & "." & sxIPTo(n)
                                LV_IPs.ListItems.Add , , sData
                            Next
                        Else
                            n = InStr(sreturn, " ")
                            m = InStr(sreturn, vbTab)
                            If n Then
                                sreturn = Left(sreturn, n - 1)
                            ElseIf m Then
                                sreturn = Left(sreturn, m - 1)
                            End If
                            LV_IPs.ListItems.Add , , sreturn
                        End If
                    End If
                End If
            Loop
        Close #lfd
        lblHosts(1) = LV_IPs.ListItems.Count
        Set m_clsPingBase = New ClassPingBase
    End Sub
    
    Private Sub Form_Resize()
    Dim x As Single
        x = Me.ScaleHeight - LV_IPs.Top - 150
        If x > 0 Then LV_IPs.Height = x
    End Sub
    
    Private Sub m_clsPingBase_PingFail(sIPAdress As String, lNewStatus As Long, ArrayIndex As Long)
        LV_IPs.ListItems(ArrayIndex + 1).SubItems(1) = "---"
        LV_IPs.ListItems.Item(ArrayIndex + 1).SmallIcon = 2
        If m_bFirstRun Then
            If LV_IPs.ListItems(ArrayIndex + 1).ListSubItems(1).Tag <> -1 Then
                '//Notify state change
                LV_IPs.ListItems(ArrayIndex + 1).ListSubItems(1).ReportIcon = 4
            End If
        End If
    End Sub
    
    'Private Sub m_clsPingBase_PingFail(sIPAdress As String, lNewStatus As Long)
    'Dim lvitem As ListItem
    '    Set lvitem = LV_IPs.FindItem(sIPAdress)
    '    If Not lvitem Is Nothing Then
    '        lvitem.SubItems(1) = "--"
    '        lvitem.EnsureVisible
    '    End If
    'End Sub
    '
    'Private Sub m_clsPingBase_PingSuccess(sIPAdress As String, lNewStatus As Long)
    'Dim lvitem As ListItem
    '    Set lvitem = LV_IPs.FindItem(sIPAdress)
    '    If Not lvitem Is Nothing Then
    '        lvitem.SubItems(1) = lNewStatus
    '        lvitem.EnsureVisible
    '    End If
    'End Sub
    Private Sub m_clsPingBase_PingSuccess(sIPAdress As String, lNewStatus As Long, ArrayIndex As Long)
        LV_IPs.ListItems(ArrayIndex + 1).SubItems(1) = lNewStatus
        LV_IPs.ListItems(ArrayIndex + 1).EnsureVisible
        LV_IPs.ListItems.Item(ArrayIndex + 1).SmallIcon = 1
        If m_bFirstRun Then
            If LV_IPs.ListItems(ArrayIndex + 1).ListSubItems(1).Tag = -1 Then
                '//Notify state change
                LV_IPs.ListItems(ArrayIndex + 1).ListSubItems(1).ReportIcon = 3
            End If
        
        End If
    End Sub
    there is also some thread in this forum, but i never got it to work correctly
    i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case.
    Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next

    dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part

    come back and mark your original post as resolved if your problem is fixed
    pete

  4. #4

    Thread Starter
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: IcmpSendEcho2 with APC call back

    Thanks guys. This is exactly what I need. @westconn1 - > Is there a reason you create an ICMP handle for every ping? In my code I just create on ICMP handle and use it for all the pings. Is this incorrect somehow?

    @crazyDude IcmpSendEcho2 cannot do sub millisecond management but I think I can make that work with queryPerformanceCounter and remembering the start time.

    cheers guys

  5. #5
    PowerPoster
    Join Date
    Dec 2004
    Posts
    25,618

    Re: IcmpSendEcho2 with APC call back

    as stated, i did not write the code but as the calls are asyncronous, i would assume that the previous icmp handle would still be in use, when the next however many pings occur, easier not to try to reuse
    i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case.
    Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next

    dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part

    come back and mark your original post as resolved if your problem is fixed
    pete

  6. #6

    Thread Starter
    Member
    Join Date
    Jun 2013
    Posts
    43

    Re: IcmpSendEcho2 with APC call back

    One final question. Is my declaration of the ioStatusBlockCorrect

    Private Type IO_STATUS_BLOCK
    Status As Long
    Information As Long
    End Type

    And what should I expect to see in it when using a call back?

    cheers

  7. #7
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: IcmpSendEcho2 with APC call back

    This may be helpful, google: "nstatus.h" download
    There are lots and lots of status codes. As for which in the that file could typically be returned from pinging, others may be able to answer that question. Note: a value of 0 is STATUS_SUCCESS
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  8. #8
    Addicted Member
    Join Date
    Feb 2014
    Location
    USA
    Posts
    128

    Re: IcmpSendEcho2 with APC call back

    Quote Originally Posted by vbcommander View Post
    @crazyDude IcmpSendEcho2 cannot do sub millisecond management but I think I can make that work with queryPerformanceCounter and remembering the start time.
    If you get sub-millisecond timing from that, please post back and let me know!

    Quote Originally Posted by vbcommander View Post
    One final question. Is my declaration of the ioStatusBlockCorrect

    Private Type IO_STATUS_BLOCK
    Status As Long
    Information As Long
    End Type

    And what should I expect to see in it when using a call back?
    I don't think there's anything very useful to be gleaned from IO_STATUS_BLOCK. It's not required to implement APC, I do know that, and I'm not using it whatsoever.
    Last edited by CrazyDude; Jul 12th, 2018 at 02:31 PM.

  9. #9
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,470

    Re: IcmpSendEcho2 with APC call back

    Can I ask what the ping is being used for? The reason I ask is that it will probably give a reasonable return time on the Local Area Network, but will not be accurate for the Wide Area Network. This is because routers have the ability to give ICMP messages a lower priority, and will delay those messages when the router is busy. To get more accurate measurements in those cases, I use a TCP connect request and measure the time to receive the ACK.

    J.A. Coutts

  10. #10
    Addicted Member
    Join Date
    Feb 2014
    Location
    USA
    Posts
    128

    Re: IcmpSendEcho2 with APC call back

    Interesting! I always thought pings were either given higher priority or that they were closer to the what the remote device was experiencing as far as how busy the router/switch is.

    Of course a TCP ACK only works if you know which TCP port is available, if one is even available, but when you're talking about receiving the ACK, do you mean the difference between attempting the connect and acceptance or a forceful refusal? If so, I do that too, in addition to ping and UDP.

  11. #11
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,470

    Re: IcmpSendEcho2 with APC call back

    Quote Originally Posted by CrazyDude View Post
    Interesting! I always thought pings were either given higher priority or that they were closer to the what the remote device was experiencing as far as how busy the router/switch is.

    Of course a TCP ACK only works if you know which TCP port is available, if one is even available, but when you're talking about receiving the ACK, do you mean the difference between attempting the connect and acceptance or a forceful refusal? If so, I do that too, in addition to ping and UDP.
    The device has to be configured to accept pings, and many devices these days default to not accepting them. With TCP, the receiver has to have a socket listening. Servers usually listen on port 80, and local devices are usually listening on port 135. I used to use port 445, but that doesn't work any more.

    A TCP connection is a 3 way handshake. The connecting device sends a SYN request, the receiver sends a SYN ACK, and the connecting device sends back an ACK. So what I do is force an error after receiving the SYN ACK so that the connection is never established. I am presently upgrading my TTL (Time To Live) program, and will post it to the CodeBank when complete.

    J.A. Coutts

  12. #12
    Addicted Member
    Join Date
    Feb 2014
    Location
    USA
    Posts
    128

    Re: IcmpSendEcho2 with APC call back

    Quote Originally Posted by couttsj View Post
    A TCP connection is a 3 way handshake. The connecting device sends a SYN request, the receiver sends a SYN ACK, and the connecting device sends back an ACK. So what I do is force an error after receiving the SYN ACK so that the connection is never established. I am presently upgrading my TTL (Time To Live) program, and will post it to the CodeBank when complete.
    I realize how TCP connections work, but the only option I know of to do what you're saying is to just ignore the connection acceptance after requesting a connection from a remote IP. It sounds like you're saying you've found a way to send a single SYN with raw sockets even if a remote TCP port is unavailable and wait for a response. Coz I know using the normal TCP connect method, Windows will try SYNs like 3 times if there's no response from the remote IP. If you're doing it differently, I'd love to see that source code because I heard it wasn't possible in Windows. So if this is the case, please post ASAP!

  13. #13
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,470

    Re: IcmpSendEcho2 with APC call back

    Quote Originally Posted by CrazyDude View Post
    I realize how TCP connections work, but the only option I know of to do what you're saying is to just ignore the connection acceptance after requesting a connection from a remote IP. It sounds like you're saying you've found a way to send a single SYN with raw sockets even if a remote TCP port is unavailable and wait for a response. Coz I know using the normal TCP connect method, Windows will try SYNs like 3 times if there's no response from the remote IP. If you're doing it differently, I'd love to see that source code because I heard it wasn't possible in Windows. So if this is the case, please post ASAP!
    Well, not quite. The client sends a SYN request. The server responds with a SYN-ACK. At this point, I force an error on the client as it receives the SYN-ACK, so it does not respond with an ACK and the connection is never established. There still has to be a listening port, but because the connection was never established, the connection is never transferred to a new socket, and the port remains listening.

    I have run into a few issues upgrading the TTL program, but the original is posted here:
    http://www.vbforums.com/showthread.p...it-Time-Tester

    J.A. Coutts

  14. #14
    Addicted Member
    Join Date
    Feb 2014
    Location
    USA
    Posts
    128

    Re: IcmpSendEcho2 with APC call back

    I'll check that out and await what you got.

    Sorry for 'jacking your thread vbcommander!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width