# GÓC SÁNG TẠO > Khu vực lập trình > Visual Basic >  Wake On Lan – Lập trình bật máy tính từ xa

## dongoclinh

Chắc hẳn các bạn đều biết chức năng Wake On Lan (WOL) của card mạng dùng để "đánh thức" máy tính bằng tín hiệu gửi qua mạng. Nếu hiểu được nguyên lý, các bạn có thể tự viết chương trình để bật máy từ xa hoặc tích hợp phần này vào chương trình quản lý hệ thống mạng LAN của mình.*Yêu cầu hệ thống
*
*1. Với máy tính cần kích hoạt*

- Card mạng hỗ trợ WOL.

- Nếu yêu cầu kích hoạt từ trạng thái tắt thì phải có mainboard hỗ trợ WOL. Nếu card mạng rời thì phải có dây WOL cắm từ card mạng vào mainboard. Với các card mạng onboard thì hầu hết đều hỗ trợ WOL và không cần thêm dây cắm. Đồng thời phải kiểm tra thiết lập trong BIOS để đảm bảo chức năng WOL được đặt là Enable (đọc tài liệu đi theo mainboard để biết chi tiết).

- Nếu kích hoạt từ trạng thái standby thì yêu cầu hệ điều hành từ Windows 2000 trở lên hoặc các hệ điều hành khác có hỗ trợ tính năng quản lý nguồn (Power Management) tương đương, và chức năng này sẽ được bật bằng cách vào Properties của card mạng trong phần Hardware Device Manger như hình 1, đánh dấu chọn Allow this device to bring the computer out of standby.


​Ghi chú: Nếu trong Properties không có thẻ Power Management thì có nghĩa hệ thống của bạn không hỗ trợ.

*Các yêu cầu khác:
*
- Có thêm một máy để chạy chương trình điều khiển.

- Phải có Hub/Switch để cắm 2 máy trên. Mạng cắm trực tiếp 2 máy sẽ không thực hiện được vì khi một máy tắt thì kết nối mạng giữa 2 máy cũng ngắt theo, tín hiệu kích hoạt từ máy còn lại không gửi đi được.

*Tín hiệu kích hoạt*

Card mạng sẽ được kích hoạt khi nhận được tín hiệu trong các trường hợp sau:

- Nhận một gói tin đã được đăng ký trước đó.

- Nhận được một magic packet, là một gói tin chứa 16 lần liên tiếp địa chỉ cứng (MAC address) của card mạng nhận tín hiệu.

- Phát hiện một thay đổi trong kết nối, ví dụ: cắm lại dây cáp mạng.

Bài viết này sẽ sử dụng cách thứ hai, tạo một magic packet rồi gửi quảng bá (broadcast) trong mạng LAN bằng Winsock với giao thức UDP. Để gửi tin quảng bá trong mạng LAN, chúng ta gửi đến một địa chỉ đặc biệt dành riêng, có tất cả các bit trong Host ID được đặt là 1. Ví dụ, với hệ thống mạng sau:

Địa chỉ IP: 192.168.0.x/24; NetworkID = 192.168.0.0; Host ID từ 1->254; Subnet Mask = 255.255.255.0. Đây là ví dụ tiêu biểu của một mạng thuộc lớp C, trong đó 24 bit đầu của địa chỉ IP xác định Network ID, 8 bit sau xác định Host ID. Với 8 bit đó bằng 1 ta sẽ có địa chỉ quảng bá (broadcasting address) là 192.168.0.255. Để biết thêm chi tiết, các bạn có thể tìm đọc phần "Introduction to TCP/IP" trên mạng MSDN của Microsoft hoặc từ các nguồn thông tin khác.

Việc lập trình xác định các địa chỉ MAC trong mạng LAN nằm ngoài phạm vi bài viết này và xin được đề cập đến trong dịp khác. Để có được địa chỉ MAC của các máy từ xa, các bạn có thể dùng lệnh nbtstat hay ipconfig trong Win2000 hoặc dùng các phần mềm quét địa chỉ MAC có thể tải về miễn phí từ Internet (ví dụ như phần mềm Bopup Scanner cung cấp kèm theo mã nguồn).

*Chương trình kich hoạt*

Bây giờ chúng ta bắt đầu viết chương trình để thực hiện việc kích hoạt. Để cho đơn giản, tôi viết bằng Visual Basic 6.0. Khi đã hiểu nguyên lý, các bạn có thể viết bằng các ngôn ngữ lập trình khác tùy ý, hoặc phát triển thêm, hoặc tích hợp vào chương trình khác của mình.

Chạy Visual Basic, tạo một project mới, kiểu Standard EXE. Trên Form1 mặc định được tạo, chúng ta tạo thêm một hộp văn bản (Text1), một nút lệnh (Command1) và một winsock control (Winsock1) vào form rồi nhập đoạn mã nguồn (trong đó phần thông số mạng các bạn sửa theo hệ thống mạng của mình).

Bây giờ các bạn dịch và chạy thử chương trình ở các chế độ kích hoạt máy tính đang standby và mở máy tính đang tắt. Thật thú vị khi có thể ngồi một nơi mà mở được máy tính ở nơi khác. Mọi ý kiến đóng góp và thắc mắc xin vui lòng gửi về địa chỉ email của tác giả. Mã nguồn chương trình có thể tải về ở website của TGVT-PCWVN. 

*MÃ NGUỒN*


Option Explicit
Dim StrNetID As String, StrSubnetMask As String

Private Sub Form_Load()
'Thiet lap thong so mang LAN
'Neu bo qua 2 dong duoi thi Magic Packet se duoc gui toi d/chi 255.255.255.255

'StrNetID = "192.168.0.0"
'StrSubnetMask = "255.255.255.0"

'Thiet lap cac gia tri mac dinh
Text1.Text = "00-E0-7D-8F-A1-D2" 
'Dia chi MAC cua card mang
Command1.Caption = "&Send Packet"
Command1.Default = True
End Sub

Private Sub Command1_Click()
Dim ByteIndex As Long, NICAddressIndex As Long
Dim StrNICAddress As String
Dim HWAddressByteValues(0 To 5) As Byte
Dim MagicPacketData(0 To 101) As Byte
Dim StrBroadcastAddress As String

On Error GoTo Error_Handler

'Kiem tra dia chi MAC
StrNICAddress = ValidateNICAddress(Text1.Text)
If StrNICAddress = "" Then
MsgBox "Dia chi MAC khong hop le!", vbCritical
Exit Sub
End If

'Chuyen dia chi MAC tu String sang mang Byte
For ByteIndex = 0 To 5
HWAddressByteValues(ByteIndex) = 0
Next
For ByteIndex = 1 To 11 Step 2
HWAddressByteValues((ByteIndex - 1) / 2) = _
Val("&H" & Mid$(StrNICAddress, ByteIndex, 2))
Next

'Tao Magic Packet, chuoi dong bo 6 bytes
For ByteIndex = 0 To 5
MagicPacketData(ByteIndex) = 255
Next

'Tiep theo la 16 dia chi MAC address
For NICAddressIndex = 0 To 15
For ByteIndex = 0 To 5
MagicPacketData((NICAddressIndex * 6) + ByteIndex + 6) = _
HWAddressByteValues(ByteIndex)
Next
Next

'Xac dinh dia chi Broadcast
StrBroadcastAddress = GetBroadcastAddress(StrNetID, StrSubnetMask)

'Gui quang ba Magic Packet
Winsock1.RemoteHost = StrBroadcastAddress
Winsock1.Protocol = sckUDPProtocol
Winsock1.SendData MagicPacketData
Winsock1.Close

Exit Sub
Error_Handler:
MsgBox Err.Source & " error no. " & Err.Number & ": " & _
Err.Description, vbCritical
End Sub

Private Function ValidateNICAddress(MACAddress As String) As String

Const VALID_NIC_ADDRESS_LENGTH = 12
Dim HexCharIndex As Long
Dim HexChar As String
Dim InitialAddress As String
Dim ReducedAddress As String

ReducedAddress = ""
InitialAddress = UCase$(Trim$(MACAddress))

For HexCharIndex = 1 To Len(InitialAddress)
HexChar = Mid$(InitialAddress, HexCharIndex, 1)
Select Case HexChar
Case "0" To "9", "A" To "F": ReducedAddress = _
ReducedAddress & HexChar
End Select
Next

If Len(ReducedAddress) = VALID_NIC_ADDRESS_LENGTH Then
ValidateNICAddress = UCase$(ReducedAddress)
Else
ValidateNICAddress = ""
End If
End Function
Private Function GetBroadcastAddress(IPSubnetAddress As String, _
IPSubnetMask As String) As String
Dim IPStrArray() As String
Dim MaskStrArray() As String
Dim BCastAddressByte As Byte
Dim BCastAddress As String
Dim ByteIndex As Long

If IPSubnetAddress = "" Or IPSubnetMask = "" Then
GetBroadcastAddress = "255.255.255.255"
Exit Function
End If

BCastAddress = ""
IPStrArray = Split(IPSubnetAddress, ".")
MaskStrArray = Split(IPSubnetMask, ".")

For ByteIndex = 0 To 3
BCastAddressByte = Val(IPStrArray(ByteIndex)) Or _
(Val(MaskStrArray(ByteIndex)) Xor 255)
BCastAddress = BCastAddress & CStr(BCastAddressByte)
If ByteIndex < 3 Then BCastAddress = BCastAddress & "."
Next

GetBroadcastAddress = BCastAddress
End Function

_Theo pcworld_

----------

