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程式碼如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | 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 |
使用方式如下
1 2 3 4 5 6 7 8 9 10 11 | 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