none
關於 SetTcpEntry 的問題 RRS feed

  • 問題

  • 請教各位先進,

    最近在研究如何關閉已存在的連線, Google一番之後找到了 SetTcpEntry Function, 不過使用上有些狀況, 程式碼如下(抱歉, 程式碼若太長請提醒一聲)

    Imports System.Runtime.InteropServices

    <StructLayout(LayoutKind.Sequential)> Public Class MIB_TCPROW
        Public dwState As TCPState
        Public dwLocalAddr As Integer
        Public dwLocalPort As UInt32
        Public dwRemoteAddr As Integer
        Public dwRemotePort As UInt32
    End Class

    Public Enum TCPState As Integer
        MIB_TCP_STATE_CLOSED = 1
        MIB_TCP_STATE_LISTEN = 2
        MIB_TCP_STATE_SYN_SENT = 3
        MIB_TCP_STATE_SYN_RCVD = 4
        MIB_TCP_STATE_ESTAB = 5
        MIB_TCP_STATE_FIN_WAIT1 = 6
        MIB_TCP_STATE_FIN_WAIT2 = 7
        MIB_TCP_STATE_CLOSE_WAIT = 8
        MIB_TCP_STATE_CLOSING = 9
        MIB_TCP_STATE_LAST_ACK = 10
        MIB_TCP_STATE_TIME_WAIT = 11
        MIB_TCP_STATE_DELETE_TCB = 12
    End Enum

    Public Class Form1

        Private Declare Function GetTcpTable Lib "iphlpapi" (ByVal pTcpTable As IntPtr, ByRef pdwSize As Integer, ByVal bOrder As Boolean) As Integer
        Private Declare Function SetTcpEntry Lib "iphlpapi" (ByRef pTcpTable As MIB_TCPROW) As UInt32

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim a As MIB_TCPROW() = getTCPConnectionTable()
            For i As Integer = 0 To a.Length - 1
                Dim __row As MIB_TCPROW = CType(a(i), MIB_TCPROW)
                Dim __localPort As Integer = __row.dwLocalPort
                Dim __remoetIP As String = GetIpFromLong(__row.dwRemoteAddr)
                If __remoetIP = "xx.xx.xx.xx" Then ' >> 這裏想要針對某些IP中斷其連線
                    If __row.dwState = TCPState.MIB_TCP_STATE_ESTAB Then ' >> 根據 MSDN 說明, 似乎只有 established 狀態的 Connection 才可以變更狀態
                        __row.dwState = TCPState.MIB_TCP_STATE_DELETE_TCB ' >> 同上, 似乎也只能設定為 DELETE_TCB
                        MsgBox(SetTcpEntry(__row).ToString()) ' >> 這裏顯示出 SetTcpEntry 的結果, 卻永遠都是 87, "Specified port is not in state to be closed down"
                    End If
                End If
            Next
            End
        End Sub

        Private Function getTCPConnectionTable() As MIB_TCPROW()
            Dim pdwSize As Integer
            Dim iRetVal As Integer
            Dim i As Integer
            Dim TcpTableRow As MIB_TCPROW
            Dim pStructPointer As IntPtr = IntPtr.Zero
            Dim iNumberOfStructures As Integer

            iRetVal = GetTcpTable(pStructPointer, pdwSize, 0)

            pStructPointer = Marshal.AllocHGlobal(pdwSize)
            iRetVal = GetTcpTable(pStructPointer, pdwSize, 0)
            iNumberOfStructures = Math.Ceiling((pdwSize - 4) / Marshal.SizeOf(GetType(MIB_TCPROW)))

            Dim __return(iNumberOfStructures - 1) As MIB_TCPROW

            For i = 0 To iNumberOfStructures - 1
                Dim pStructPointerTemp As IntPtr = New IntPtr(pStructPointer.ToInt32() + 4 + (i * Marshal.SizeOf(GetType(MIB_TCPROW))))
                TcpTableRow = New MIB_TCPROW()
                With TcpTableRow
                    .dwLocalAddr = 0
                    .dwState = 0
                    .dwLocalPort = 0
                    .dwRemoteAddr = 0
                    .dwRemotePort = 0
                End With
                TcpTableRow = CType(Marshal.PtrToStructure(pStructPointerTemp, GetType(MIB_TCPROW)), MIB_TCPROW)
                __return(i) = TcpTableRow
            Next

            Marshal.FreeHGlobal(pStructPointer)
            Return __return
        End Function

        Private Function GetIpFromLong(ByRef lngIPAddress As Integer) As String
            Dim arrIpParts() As Byte = BitConverter.GetBytes(lngIPAddress)
            Return arrIpParts(0).ToString() + "." + arrIpParts(1).ToString() + "." + arrIpParts(2).ToString() + "." + arrIpParts(3).ToString()
        End Function

        Private Function GetTcpPortNumber(ByVal DWord As UInt32) As UInt32
            Return ((DWord >> 8) And &HFF) + ((DWord And &HFF) << 8)
        End Function

    End Class

    問題在於將狀態設定為 12, DELETE_TCB 並呼叫 SetTcpEntry 後, 永遠都只得到 87 的 return code

    曾經 Google 過此問題, 只找到個說法, 就是 PortNumber 應為 UInt32, 不過上面的程式碼中可知我已經改為 UInt32 了

    依然是傳回 87

    上方的 getTCPConnectionTable 的回傳結果, 我有稍微跟 netstat 的執行結果比對一下, 大致上差不多, IP 與 Port Number 都正確

    就是不清楚為何一直傳回 87

    請各位先進不吝指教

    2011年2月18日 下午 03:21

解答

  •  試著把MIB_TCPROW 宣告為結構而不是類別, 看看會不會有用.

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    2011年2月18日 下午 04:37
    版主

所有回覆