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