RouterOS 在3.0版以後推出了API可以讓外部程式存取
這樣子功能性真的是延伸了很多
目前API支援以下幾種程式語言
in Perl – forum thread by cheesegrits
in Delphi – forum thread and wiki by rodolfo
in PHP – wiki link by Denis Basta
Java sample methods – forum post
in Python – wiki link by Mikrotik staff
in C# – wiki link by wiki user Gregy
可惜沒有VB.NET的版本。不過只要有C#的版本,一切就好辦事了
以下是轉換過後VB.NET版的API
不過傳送或讀取的值如果是中文的話會變成亂碼,這部份要再研究一下
使用前記得先開啟API的服務
/ip service enable api 或是利用圖型介面開啟 IP->Service
VB.NET版本的RouterOS API程式碼如下
Imports System.Net.Sockets
Imports System.IO
Imports System.Text
Class MK_ROS
Private connection As Stream
Private con As TcpClient
Public Sub New(ByVal ip As String)
con = New TcpClient()
con.Connect(ip, 8728)
connection = DirectCast(con.GetStream(), Stream)
End Sub
Public Sub Close()
connection.Close()
con.Close()
End Sub
Public Function Login(ByVal username As String, ByVal password As String) As Boolean
Send("/login", True)
Dim hash As String = Read()(0).Split(New String() {"ret="}, StringSplitOptions.None)(1)
Send("/login")
Send("=name=" & username)
Send("=response=00" & EncodePassword(password, hash), True)
If Read()(0) = "!done" Then
Return True
Else
Return False
End If
End Function
Public Sub Send(ByVal co As String)
Dim bajty As Byte() = Encoding.ASCII.GetBytes(co.ToCharArray())
Dim velikost As Byte() = EncodeLength(bajty.Length)
connection.Write(velikost, 0, velikost.Length)
connection.Write(bajty, 0, bajty.Length)
End Sub
Public Sub Send(ByVal co As String, ByVal endsentence As Boolean)
Dim bajty As Byte() = Encoding.ASCII.GetBytes(co.ToCharArray())
Dim velikost As Byte() = EncodeLength(bajty.Length)
connection.Write(velikost, 0, velikost.Length)
connection.Write(bajty, 0, bajty.Length)
connection.WriteByte(0)
End Sub
Public Function Read() As List(Of String)
Dim output As New List(Of String)()
Dim o As String = ""
Dim tmp As Byte() = New Byte(3) {}
Dim count As Long
While True
tmp(3) = CByte(connection.ReadByte())
'if(tmp[3] == 220) tmp[3] = (byte)connection.ReadByte(); it sometimes happend to me that
'mikrotik send 220 as some kind of "bonus" between words, this fixed things, not sure about it though
If tmp(3) = 0 Then
output.Add(o)
If o.Substring(0, 5) = "!done" Then
Exit While
Else
o = ""
Continue While
End If
Else
If tmp(3) < &H80 Then
count = tmp(3)
Else
If tmp(3) < &HC0 Then
Dim tmpi As Integer = BitConverter.ToInt32(New Byte() {CByte(connection.ReadByte()), tmp(3), 0, 0}, 0)
count = tmpi Xor &H8000
Else
If tmp(3) < &HE0 Then
tmp(2) = CByte(connection.ReadByte())
Dim tmpi As Integer = BitConverter.ToInt32(New Byte() {CByte(connection.ReadByte()), tmp(2), tmp(3), 0}, 0)
count = tmpi Xor &HC00000
Else
If tmp(3) < &HF0 Then
tmp(2) = CByte(connection.ReadByte())
tmp(1) = CByte(connection.ReadByte())
Dim tmpi As Integer = BitConverter.ToInt32(New Byte() {CByte(connection.ReadByte()), tmp(1), tmp(2), tmp(3)}, 0)
count = tmpi Xor &HE0000000
Else
If tmp(3) = &HF0 Then
tmp(3) = CByte(connection.ReadByte())
tmp(2) = CByte(connection.ReadByte())
tmp(1) = CByte(connection.ReadByte())
tmp(0) = CByte(connection.ReadByte())
count = BitConverter.ToInt32(tmp, 0)
Else
'Error in packet reception, unknown length
Exit While
End If
End If
End If
End If
End If
End If
For i As Integer = 0 To count - 1
o += ChrW(connection.ReadByte())
Next
End While
Return output
End Function
Private Function EncodeLength(ByVal delka As Integer) As Byte()
If delka < &H80 Then
Dim tmp As Byte() = BitConverter.GetBytes(delka)
Return New Byte(0) {tmp(0)}
End If
If delka < &H4000 Then
Dim tmp As Byte() = BitConverter.GetBytes(delka Or &H8000)
Return New Byte(1) {tmp(1), tmp(0)}
End If
If delka < &H200000 Then
Dim tmp As Byte() = BitConverter.GetBytes(delka Or &HC00000)
Return New Byte(2) {tmp(2), tmp(1), tmp(0)}
End If
If delka < &H10000000 Then
Dim tmp As Byte() = BitConverter.GetBytes(delka Or &HE0000000)
Return New Byte(3) {tmp(3), tmp(2), tmp(1), tmp(0)}
Else
Dim tmp As Byte() = BitConverter.GetBytes(delka)
Return New Byte(4) {&HF0, tmp(3), tmp(2), tmp(1), tmp(0)}
End If
End Function
Public Function EncodePassword(ByVal Password As String, ByVal hash As String) As String
Dim hash_byte As Byte() = New Byte(hash.Length / 2 - 1) {}
For i As Integer = 0 To hash.Length - 2 Step 2
hash_byte(i / 2) = [Byte].Parse(hash.Substring(i, 2), System.Globalization.NumberStyles.HexNumber)
Next
Dim heslo As Byte() = New Byte(1 + Password.Length + (hash_byte.Length - 1)) {}
heslo(0) = 0
Encoding.ASCII.GetBytes(Password.ToCharArray()).CopyTo(heslo, 1)
hash_byte.CopyTo(heslo, 1 + Password.Length)
Dim hotovo As Byte()
Dim md5 As System.Security.Cryptography.MD5
md5 = New System.Security.Cryptography.MD5CryptoServiceProvider()
hotovo = md5.ComputeHash(heslo)
'Convert encoded bytes back to a 'readable' string
Dim navrat As String = ""
For Each h As Byte In hotovo
navrat += h.ToString("x2")
Next
Return navrat
End Function
End Class
使用方式如下
Dim mikrotik As New MK_ROS("主機位置(可為IP或Domain)")
If Not mikrotik.Login("帳號", "密碼") Then
TextBox1.Text &= ("連線失敗")
mikrotik.Close()
Return
End If
'要下的指令
mikrotik.Send("/system/identity/print", True)
For Each h As String In mikrotik.Read()
TextBox1.Text &= h
Next
參考資料:

你好,看了你的日志很受启发,有个疑问能否帮解答一下?
程序退出的时候,ros里的active user仍然记录着我的登录信息,该怎么办哈,我已经使用了 close方法
這個問題目前無法解決,只能透過重新啟動ROS的方式清楚
官方正在動手修正中
相關的討論可以看官方討論區
http://forum.mikrotik.com/viewtopic.php?f=9&t=37075
官方表示該問題在RouterOS V5 的版本解決
V4版本,仍是無解
http://forum.mikrotik.com/viewtopic.php?p=230507#p230507