class MK { Stream connection; TcpClient con; public MK(string ip,int port) { con = new TcpClient(); con.Connect(ip, port); connection = (Stream)con.GetStream(); } public void Close() { connection.Close(); con.Close(); } public bool Login(string username, string password) { Send("/login", true); string hash = 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") { return true; } else { return false; } } public void Send(string co) { byte[] bajty = Encoding.GetEncoding("GB2312").GetBytes(co.ToCharArray()); byte[] velikost = EncodeLength(bajty.Length); connection.Write(velikost, 0, velikost.Length); connection.Write(bajty, 0, bajty.Length); } public void Send(string co, bool endsentence) { byte[] bajty = Encoding.GetEncoding("GB2312").GetBytes(co.ToCharArray()); byte[] velikost = EncodeLength(bajty.Length); connection.Write(velikost, 0, velikost.Length); connection.Write(bajty, 0, bajty.Length); connection.WriteByte(0); } public List<string> Read() { List<string> output = new List<string>(); string o = ""; byte[] tmp = new byte[4]; long count; while (true) { tmp[3] = (byte)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) { output.Add(o); if (o.Substring(0, 5) == "!done") { break; } else { o = ""; continue; } } else { if (tmp[3] < 0x80) { count = tmp[3]; } else { if (tmp[3] < 0xC0) { int tmpi = BitConverter.ToInt32(new byte[] { (byte)connection.ReadByte(), tmp[3], 0, 0 }, 0); count = tmpi ^ 0x8000; } else { if (tmp[3] < 0xE0) { tmp[2] = (byte)connection.ReadByte(); int tmpi = BitConverter.ToInt32(new byte[] { (byte)connection.ReadByte(), tmp[2], tmp[3], 0 }, 0); count = tmpi ^ 0xC00000; } else { if (tmp[3] < 0xF0) { tmp[2] = (byte)connection.ReadByte(); tmp[1] = (byte)connection.ReadByte(); int tmpi = BitConverter.ToInt32(new byte[] { (byte)connection.ReadByte(), tmp[1], tmp[2], tmp[3] }, 0); count = tmpi ^ 0xE0000000; } else { if (tmp[3] == 0xF0) { tmp[3] = (byte)connection.ReadByte(); tmp[2] = (byte)connection.ReadByte(); tmp[1] = (byte)connection.ReadByte(); tmp[0] = (byte)connection.ReadByte(); count = BitConverter.ToInt32(tmp, 0); } else { //Error in packet reception, unknown length break; } } } } } } for (int i = 0; i < count; i++) { o += (Char)connection.ReadByte(); } } return output; } byte[] EncodeLength(int delka) { if (delka < 0x80) { byte[] tmp = BitConverter.GetBytes(delka); return new byte[1] { tmp[0] }; } if (delka < 0x4000) { byte[] tmp = BitConverter.GetBytes(delka | 0x8000); return new byte[2] { tmp[1], tmp[0] }; } if (delka < 0x200000) { byte[] tmp = BitConverter.GetBytes(delka | 0xC00000); return new byte[3] { tmp[2], tmp[1], tmp[0] }; } if (delka < 0x10000000) { byte[] tmp = BitConverter.GetBytes(delka | 0xE0000000); return new byte[4] { tmp[3], tmp[2], tmp[1], tmp[0] }; } else { byte[] tmp = BitConverter.GetBytes(delka); return new byte[5] { 0xF0, tmp[3], tmp[2], tmp[1], tmp[0] }; } } public string EncodePassword(string Password, string hash) { byte[] hash_byte = new byte[hash.Length / 2]; for (int i = 0; i <= hash.Length - 2; i += 2) { hash_byte[i / 2] = Byte.Parse(hash.Substring(i, 2), System.Globalization.NumberStyles.HexNumber); } byte[] heslo = new byte[1 + Password.Length + hash_byte.Length]; heslo[0] = 0; Encoding.ASCII.GetBytes(Password.ToCharArray()).CopyTo(heslo, 1); hash_byte.CopyTo(heslo, 1 + Password.Length); Byte[] hotovo; System.Security.Cryptography.MD5 md5; md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); hotovo = md5.ComputeHash(heslo); //Convert encoded bytes back to a 'readable' string string navrat = ""; foreach (byte h in hotovo) { navrat += h.ToString("x2"); } return navrat; } }
此类操作类,不需要修改,直接引用即可
下面这是一个 ROS 的 activeuser类
class RosMkClass { AppSetting _setting; public RosMkClass(AppSetting setting) { _setting = setting; } /// <summary> /// 软路由返回的消息类 /// </summary> class Ros_Message { /// <summary> /// 是否成功,成功为true 不成功为false /// </summary> public bool Success { get; set; } /// <summary> /// 软路由返回的消息 /// </summary> public string Message { get; set; } } private Ros_Message fenxi(List<string> list) { Ros_Message message = new Ros_Message(); message.Success = false; foreach (string item in list) { Regex reg1 = new Regex(@"(?<=message=).*(?=.tag)"); Regex reg2 = new Regex(@"(?<=ret=*).*(?=.tag)"); if (item.IndexOf("message") > 0) { message.Message = reg1.Match(item).ToString(); message.Success = false; break; } if (item.IndexOf("ret") > 0) { message.Message = reg2.Match(item).ToString(); message.Success = true; break; } if (item.IndexOf("done") > 0) { message.Success = true; break; } } return message; } public class RosActiveUser { public RosActiveUser(string RetString) { Regex rg = new Regex(@"(?<=.id=*).*(?==name)"); _ID = rg.Match(RetString).ToString(); rg = new Regex(@"(?<=name=).*(?==service)"); _username = rg.Match(RetString).ToString(); rg = new Regex(@"(?<=caller-id=).*(?==address)"); _macaddress = rg.Match(RetString).ToString(); } private string _ID; public string ID { get { return _ID; } set { _ID = value; } } private string _username; public string Username { get { return _username; } set { _username = value; } } private string _macaddress; public string MacAddress { get { return _macaddress; } set { _macaddress = value; } } } private List<RosActiveUser> activelist() { MK mk = new MK(_setting.Ros_IP, _setting.Ros_Port); List<string> list = new List<string>(); List<RosActiveUser> activelist = new List<RosActiveUser>(); if (mk.Login(_setting.Ros_Admin, _setting.Ros_Password)) { mk.Send(string.Format("/ppp/active/print")); mk.Send(".tag=act", true); list.AddRange(mk.Read()); mk.Close(); } foreach (string item in list) { if (item.IndexOf(".tag=act") > 0) { activelist.Add(new RosActiveUser(item)); } } return activelist; } private Ros_Message Ros_ActiveRemove(string username) { List<RosActiveUser> ActList = activelist(); List<string> list = new List<string>(); RosActiveUser act = ActList.Find(a => a.Username == username); if (act != null) { MK mk = new MK(_setting.Ros_IP, _setting.Ros_Port); if (mk.Login(_setting.Ros_Admin, _setting.Ros_Password)) { mk.Send("/ppp/active/remove"); mk.Send(string.Format("=.id=*{0}", act.ID)); //"=.id=张刚" mk.Send(".tag=ss1", true); list.AddRange(mk.Read()); mk.Close(); } } return fenxi(list); } private Ros_Message Ros_SecretRemove(string name) { List<string> list = new List<string>(); MK mk = new MK(_setting.Ros_IP, _setting.Ros_Port); if (mk.Login(_setting.Ros_Admin, _setting.Ros_Password)) { mk.Send("/ppp/secret/remove"); mk.Send(string.Format("=.id={0}", name)); //"=.id=张刚" mk.Send(".tag=ss1", true); list.AddRange(mk.Read()); mk.Close(); } return fenxi(list); } private Ros_Message Ros_Create(Teacher teacher) { List<string> list = new List<string>(); MK mk = new MK(_setting.Ros_IP, _setting.Ros_Port); if (mk.Login(_setting.Ros_Admin, _setting.Ros_Password)) { mk.Send("/ppp/secret/add"); mk.Send(string.Format("=name={0}", teacher.UserName)); mk.Send(string.Format("=password={0}", teacher.Password)); mk.Send(string.Format("=service={0}", "pppoe")); mk.Send(string.Format("=profile=profile{0}", teacher.Level)); mk.Send(string.Format("=comment={0}", teacher.Name)); mk.Send(".tag=ss2", true); list.AddRange(mk.Read()); mk.Close(); } return fenxi(list); } /// <summary> /// 查看 ROS 是不否可以连接成功.检测 ROS 的设置参数. /// </summary> /// <returns>是否连接成功!</returns> public bool Ros_Connected() { bool isconn = false; MK mk = new MK(_setting.Ros_IP, _setting.Ros_Port); isconn = mk.Login(_setting.Ros_Admin, _setting.Ros_Password); mk.Close(); return isconn; } public string UpdateAccount(Teacher teacher) //汉字姓名 { Ros_Message sec = Ros_SecretRemove(teacher.Name); Ros_Message sct = Ros_ActiveRemove(teacher.Oldname); Ros_Message ms = Ros_Create(teacher); return ms.Success + ":" +sec.Message+"&&"+sct.Message+"&&"+ms.Message; } public string RemoveActive(string oldname) { return Ros_ActiveRemove(oldname).Message; } }
注意以下几点
修改 class MK 里面的文件
将
byte[] bajty = Encoding.ASCII.GetBytes(co.ToCharArray());
修改为
byte[] bajty = Encoding.GetEncoding("GB2312").GetBytes(co.ToCharArray());
即可接收汉字了
删除用户的时候,需要 使用 ID编号 如 *212