Option Explicit
' ฟังค์ชั่นที่แปลงหมายเลข IPv4 ให้กลายเป็นเลขจำนวนเต็มแบบไม่คิดเครื่องหมายแทน (มีแต่ 0 กับ เลขบวก) เช่น
' จาก 192.168.1.20 ก็จะกลายเป็น 335653056 แทน แต่ใช้งานจริงมันจะต้องประมวลผลในเลขฐาน 2 น่ะครับ
Public Declare Function inet_addr Lib "wsock32.dll" ( _
ByVal s As String) _
As Long
' ส่วนนี้อธิบายในโค้ดด้านล่างครับ
Public Declare Function SendARP Lib "iphlpapi.dll" ( _
ByVal DestIP As Long, _
ByVal SrcIP As Long, _
pMacAddress As Long, _
pMacAddressLen As Long _
) As Long
' การชี้ตำแหน่งของ Memory Address
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
Destination As Any, _
Source As Any, _
ByVal Length As Long _
)
' ตัวแปรแบบ Global ในฟอร์มนี้ โปรแกรมย่อยทุกๆตัว จะสามารถใช้งานได้
' เอาไว้เก็บค่าคำตอบครับ
Dim sRemoteMacAddress As String
' ##############################################################
' ฟังค์ชั่นย่อยในการตรวจสอบหาค่า MAC Address
Public Function GetMAC(strIPAddress As String) As String
' ##############################################################
If Len(strIPAddress) > 0 Then
' ส่งค่า IP Address ไปให้กับฟังค์ชั่น GetRemoteAddress
' กรณีสามารถหาค่า MAC Address ได้ ฟังค์ชั่นจะ Return ค่าจริง (True) กลับมา
If GetRemoteMACAddress(strIPAddress) Then
GetMAC = sRemoteMacAddress
' มีข้อผิดพลาด
Else
GetMAC = "SendARP Fail"
End If
End If
sRemoteMacAddress = ""
End Function
' ##############################################################
' ส่งค่า IP Address มาให้ฟังค์ชั่น ส่วนฟังค์ชั่นจะคืนค่ากลับแบบ Boolean เพื่อแจ้งว่าทำงานสำเร็จหรือไม่
Function GetRemoteMACAddress( _
sRemoteIP As String _
) As Boolean
' ##############################################################
Dim dwRemoteIP As Long
Dim pMacAddress As Long
' ให้ Pointer ที่ชี้ไปยังตำแหน่งค่าที่เก็บ MAC Address เอาไว้ 6 ชุด
Dim bpMacAddress() As Byte
' กำหนดให้ MAC Address มีความยาว 6 ชุด
Dim pMacAddrLen As Long
Dim Count As Long
' เปลี่ยนค่า IP เป็นค่าตัวเลขแบบ Long ก่อน ด้วยฟังค์ชั่น inet_addr ให้สังเกตด้วยว่าเจ้าตัวนี้มันเป็น API
' ดังนั้นโค้ดนี้จึงไม่จำเป็นต้องเลือกใช้งาน WinSock Control น่ะครับ
dwRemoteIP = inet_addr(sRemoteIP)
If dwRemoteIP <> 0 Then
' กำหนดชุดเลขฐาน 16 ของ MAC Address ไว้ 6 ตัว (MAC Address มันมีขนาด 6 ไบต์)
pMacAddrLen = 6
' ค้นหา Remote MAC Address ด้วย API32 (ฟังค์ชั่น SendARP)
' อ่านรายละเอียดเพิ่มเติม
' ARP เป็นโปรโตคอล สำหรับใช้ในเครือข่ายระดับชั้น Data Link Layer (ชั้นที่ 2)
' หน้าที่ของ ARP กับเครือข่าย TCP/IP คือ ช่วยแปลง IP Address ไปสู่ Hardware Address
' เช่น MAC Address ซึ่งเป็นเลขฐาน 16 ขนาด 6 ไบต์ หรือ 6 ชุดๆละ 1 ไบต์ เช่น 00-13-D4-9E-5B-DB
' ให้สังเกตด้วยว่า SendARP มันจะ Return ค่ากลับเป็นตัวเลขจำนวนเต็มแบบ Long
' หากมันส่งค่ากลับมา ไม่เท่ากับ 0 นั่นคือ เกิด Error ขึ้นมาน่ะครับ ก็ให้จบออกไปจากฟังค์ชั่นเลย
' ปัญหาเกิดจากสาเหตุหลักๆ คือ ใส่หมายเลข IP ผิดไป หรือ หา IP ไม่พบในระบบเครือข่าย
If SendARP(dwRemoteIP, 0&, pMacAddress, pMacAddrLen) = 0 Then
' เงื่อนไข AND หากอินพุตตัวใดตัวหนึ่งเป็น False คำตอบจะเป็น False ทันที
If pMacAddress <> 0 And pMacAddrLen <> 0 Then
' มันจะมีการส่งค่า Pointer เพื่อชี้ตำแหน่งเก็บข้อมูลของ MAC Address
' ดังนั้นต้องจัดเก็บข้อมูลลงใน Array 6 ชุด หรือ 6 ตำแหน่ง
ReDim bpMacAddress(0 To pMacAddrLen - 1)
' คัดลอกตำแหน่งแรก หรือ เริ่มต้น (0) ที่ต้องการชี้ไปหา และ นับไปอีก 6 ตำแหน่ง
' ชี้ตำแหน่งเท่านั้นน่ะครับ ส่วนค่าที่เก็บ คือ MAC Address ขนาด 1 ไบต์ (รวมกันแล้ว 6 ตัว)
' เช่น 00-13-D4-9E-5B-DB แต่ละชุดที่คั่นด้วยเครื่องหมาย - จะมีขนาด 1 ไบต์ หรือ 8 บิต
CopyMemory bpMacAddress(0), pMacAddress, ByVal pMacAddrLen
' วนรอบเพื่อหาค่าแต่ละตำแหน่ง
For Count = 0 To pMacAddrLen - 1
' เช่น ลองทดสอบ Debug ดูใน Immediate Windows ก็จะเห็นตำแหน่ง Address ที่ชี้ไป เช่น
' ? VarPtr(bpMacAddress(1))
' อ่านค่าตำแหน่งเลขฐาน 10 จะได้ 140001186 หรือ
' ? Hex$(VarPtr(bpMacAddress(1)))
' อ่านค่าตำแหน่งเลขฐาน 16 จะได้ 8583 FA2 (ค่าในแต่ละเครื่อง และ แต่ละครั้งจะได้ไม่เหมือนกันน่ะครับ)
' หากอยากรู้ค่า MAC Address เลขฐาน 16 ก็พิมพ์ในหน้าต่าง Immediate Windows
' ? Hex$(bpMacAddress(1)) ... จะได้คำตอบ คือ 13 (เลขฐาน 16)
' จากนั้นก็จะเอาค่าที่อยู่ Hex$(bpMacAddress(Count)) ในตำแหน่งที่ชี้ไปนั้นออกมาเก็บในตัวแปร Array
' นี่คือ Pointer In The Visual Basic ... คือ มันชี้ไปตำแหน่ง Memory Address แต่เอาค่าที่อยู่ในตำแหน่งนั้นมาน่ะครับ
If Count = pMacAddrLen - 1 Then
' เป็นชุดสุดท้าย จึงไม่ต้องเอาเครื่องหมาย - มาต่อท้ายครับ
sRemoteMacAddress = sRemoteMacAddress & Right("00" & Hex$(bpMacAddress(Count)), 2)
Else
' อ่านค่า MAC Address จาก 5 ตัวแรก ... ที่เห็นโค้ดด้านล่างแบบนี้ก็เพราะ
' ชุดแรกมันได้ค่า 0 ออกมาเพียงตัวเดียวน่ะครับ ... ต้องลอง Debug ดูจะมองเห็น
sRemoteMacAddress = sRemoteMacAddress & Right("00" & Hex$(bpMacAddress(Count)) & "-", 3)
End If
Next
' คืนค่ากลับเป็น True เพื่อแสดงว่าสามารถทำงานได้ถูกต้อง
If Len(sRemoteMacAddress) > 0 Then GetRemoteMACAddress = True
' ออกจากฟังค์ชั่นไปได้เลย
Exit Function
Else
' เกิดข้อผิดพลาด pMacAddress <> 0 And pMacAddrLen <> 0
' กรณี AND ... หาก Input ตัวใดตัวหนึ่งเป็น False คำตอบจะเป็น False เสมอ
GetRemoteMACAddress = False
End If
Else
' เกิดข้อผิดพลาด SendARP ส่งค่ากลับมาเป็น 0
GetRemoteMACAddress = False
End If
Else
' เกิดข้อผิดพลาด dwRemoteIP ทำการเปลี่ยนค่า IP มีค่าเป็น 0
GetRemoteMACAddress = False
End If
End Function
|