Ver Fonte

first commit

Voll Young há 9 anos atrás
commit
d833c19be7

+ 169 - 0
.gitignore

@@ -0,0 +1,169 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+
+[Dd]ebug/
+[Rr]elease/
+x64/
+build/
+[Bb]in/
+[Oo]bj/
+
+# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
+!packages/*/build/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.log
+*.scc
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+*.ncrunch*
+.*crunch*.local.xml
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.Publish.xml
+*.pubxml
+
+# NuGet Packages Directory
+## TODO: If you have NuGet Package Restore enabled, uncomment the next line
+#packages/
+
+# Windows Azure Build Output
+csx
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.[Pp]ublish.xml
+*.pfx
+*.publishsettings
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+App_Data/*.mdf
+App_Data/*.ldf
+
+# =========================
+# Windows detritus
+# =========================
+
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Mac crap
+.DS_Store
+
+# backup files
+*.bak
+
+# log files
+*.log
+
+*.orig
+
+$tf*/
+
+[Ll]og[Ff]iles/
+[Uu]pload/
+[Ss]erialize[Dd]ata/
+Version/
+!JXPT2_Dev/Web/WebComponents/ffmpeg/bin/
+JXPT2_Dev/Web/View/nbproject/
+JXPT2_Dev/Lib/*.xml
+JXPT2_Dev/Web/Configurations/systempath.config

+ 22 - 0
MyMemcached.sln

@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.21005.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyMemcached", "MyMemcached\MyMemcached.csproj", "{12B4613A-9C5B-4590-AC69-AF5FA090C37B}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{12B4613A-9C5B-4590-AC69-AF5FA090C37B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{12B4613A-9C5B-4590-AC69-AF5FA090C37B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{12B4613A-9C5B-4590-AC69-AF5FA090C37B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{12B4613A-9C5B-4590-AC69-AF5FA090C37B}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

BIN
MyMemcached/25.ico


+ 10 - 0
MyMemcached/App.config

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <appSettings>
+    <!-- 服务器列表,多个用逗号分隔 (host:port)-->
+    <add key="servers" value="127.0.0.1:11211,192.168.8.7:11211"/>
+  </appSettings>
+    <startup> 
+        
+    <supportedRuntime version="v2.0.50727"/></startup>
+</configuration>

+ 314 - 0
MyMemcached/DAO/Stats.cs

@@ -0,0 +1,314 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Data;
+using System.Text.RegularExpressions;
+using Enyim.Caching.Configuration;
+using Enyim.Caching.Memcached;
+using System.Net;
+using System.Reflection;
+using System.Collections;
+
+namespace MyMemcached.DAO
+{
+    public class Stats
+    {
+        public static Dictionary<string, mcacheClientExt> MClientList = new Dictionary<string, mcacheClientExt>();
+        static readonly object padlock = new object();
+        public static mcacheClientExt MClient(IPEndPoint EP)
+        {
+            lock (padlock)
+            {
+                if (!MClientList.ContainsKey(EP.ToString()))
+                {
+                    MemcachedClientConfiguration _config = new MemcachedClientConfiguration();
+                    _config.Servers.Add(EP);
+                    _config.NodeLocator = typeof(DefaultNodeLocator);
+                    _config.KeyTransformer = new DefaultKeyTransformer();
+                    _config.Transcoder = new DefaultTranscoder();
+                    MClientList.Add(EP.ToString(), new mcacheClientExt(_config));
+                }
+                return MClientList[EP.ToString()];
+            }
+
+        }
+
+        public DataTable AllServerStats { get; set; }
+
+        /// <summary>
+        /// 获取所有memcached服务器的状态
+        /// </summary>
+        /// <returns></returns>
+        public DataTable GetAllServerStats()
+        {
+            DataTable ServerStats = new DataTable();
+            ServerStats.Columns.Add("Server");
+            ServerStats.PrimaryKey = new[] { ServerStats.Columns["Server"] };
+            foreach (var server in Servers.ServerList.Values)
+            {
+                DataRow row = ServerStats.NewRow();
+                row["Server"] = string.Format("{0}:{1}", server.Hostname, server.Port);
+
+                foreach (var info in GetServerStats(server))
+                {
+                    if (!ServerStats.Columns.Contains(info.Key))
+                    {
+                        ServerStats.Columns.Add(info.Key);
+                    }
+                    row[info.Key] = info.Value;
+                }
+                ServerStats.Rows.Add(row);
+            }
+            AllServerStats = ServerStats;
+            return ServerStats;
+        }
+
+        /// <summary>
+        /// 获取指定服务器状态
+        /// </summary>
+        /// <param name="server"></param>
+        /// <returns></returns>
+        public Dictionary<string, string> GetServerStats(TelnetConnection server)
+        {
+            Dictionary<string, string> result = new Dictionary<string, string>();
+            server.WriteLine("stats");
+            string[] statsinfo = Regex.Split(server.Read().Trim(), "STAT");
+            foreach (string stat in statsinfo)
+            {
+                if (stat.Equals(string.Empty)) { continue; }
+                string[] info = Regex.Split(stat.Trim(), @"\s+");
+                result.Add(info[0], info[1]);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// 返回指定服务器的区块状态
+        /// </summary>
+        /// <param name="server"></param>
+        /// <returns></returns>
+        public Dictionary<string, object> StatSlabs(TelnetConnection server)
+        {
+            return GetinfoByCmd(server, "stats slabs");
+        }
+
+        public Dictionary<string, object> StatsItems(TelnetConnection server)
+        {
+            return GetinfoByCmd(server, "stats items");
+        }
+
+        /// <summary>
+        /// 格式化输出数据
+        /// </summary>
+        /// <param name="server"></param>
+        /// <param name="cmd"></param>
+        /// <returns></returns>
+        private Dictionary<string, object> GetinfoByCmd(TelnetConnection server, string cmd)
+        {
+            Dictionary<string, object> result = new Dictionary<string, object>();
+            Dictionary<string, string> infoResult = new Dictionary<string, string>();
+            server.WriteLine(cmd);
+
+            string[] statsinfo = cmd.Equals("stats items") ?
+                Regex.Split(server.Read().Trim(), "STAT items:")
+                : Regex.Split(server.Read().Trim(), "STAT");
+            foreach (string stat in statsinfo)
+            {
+                if (stat.Equals(string.Empty)) { continue; }
+                if (stat.Contains(":"))
+                {
+                    string[] info = Regex.Split(stat.Trim(), ":");
+                    if (!result.ContainsKey(info[0]))
+                    {
+                        infoResult = new Dictionary<string, string>();
+                    }
+
+                    string[] slabsinfo = Regex.Split(info[1], @"\s+");
+                    infoResult.Add(slabsinfo[0], slabsinfo[1]);
+                    result[info[0]] = infoResult;
+                }
+                else
+                {
+                    string[] info = Regex.Split(stat.Trim(), @"\s+");
+                    if (info.Length > 1)
+                    {
+                        result.Add(info[0], info[1]);
+                    }
+                }
+            }
+            return result;
+        }
+
+        public bool StatsReset(TelnetConnection server)
+        {
+            server.WriteLine("stats reset");
+            return server.Read().Trim().CompareTo("RESET") == 0;
+        }
+
+        public bool FlushAll(TelnetConnection server)
+        {
+            server.WriteLine("flush_all");
+            return server.Read().Trim().CompareTo("OK") == 0;
+        }
+
+        public string Delete(TelnetConnection server,string key)
+        {
+            server.WriteLine(string.Format("delete {0}",key));
+            return server.Read().Trim();
+        }
+
+        public Dictionary<string, string> CacheDump(TelnetConnection server, string slab, string count)
+        {
+            Dictionary<string, string> result = new Dictionary<string, string>();
+            server.WriteLine(string.Format("stats cachedump {0} {1}", slab, count));
+            string[] CacheInfo = Regex.Split(server.Read().Trim().TrimEnd('E', 'N', 'D'), "ITEM");
+            foreach (string cache in CacheInfo)
+            {
+                if (cache.Equals(string.Empty)) { continue; }
+                string[] info = Regex.Split(cache.Trim(), @"\s+\[");
+                result.Add(info[0], "[" + info[1]);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// 获取数据
+        /// </summary>
+        /// <param name="server"></param>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        public Dictionary<string, string> Get(TelnetConnection server, string key)
+        {
+            Dictionary<string, string> result = new Dictionary<string, string>();
+
+            var mc = MClient(new IPEndPoint(IPAddress.Parse(server.Hostname), server.Port));
+
+            object val;
+            var r = mc.ExecuteTryGet(key.Trim(), out val);
+            if (r.HasValue)
+            {
+                try
+                {
+                    result.Add("value", r.Value.ToString());
+                }
+                catch
+                {
+                    object obj = r.Value;
+                    StringBuilder valToString = new StringBuilder();
+                    foreach (PropertyInfo i in obj.GetType().GetProperties())
+                    {
+                        if (i.PropertyType == typeof(string))
+                        {
+                            try
+                            {
+                                valToString.AppendFormat("{0}={1}{2}", i.Name, i.GetValue(obj, new object[0]).ToString(), Environment.NewLine);
+                            }
+                            catch { }
+                        }
+                        else if (i.PropertyType.Namespace.Contains("System.Collections"))
+                        {
+                            valToString.AppendFormat("{0}=List[{2}{1}{2}]{2}", i.Name, ParsingIEnumerable(i.GetValue(obj, null) as IEnumerable), Environment.NewLine);
+                        }
+                        else
+                        {
+                            valToString.AppendFormat("{0}={1}{2}", i.Name, i.GetValue(obj, null), Environment.NewLine);
+                        }
+                    }
+                    result.Add("value", valToString.ToString());
+                }
+                result.Add("type", r.Value.GetType().ToString());
+                if (val != null)
+                {
+                    result["type"] = val.ToString();
+                }
+            }
+            else
+            {
+                result.Add("value", r.Message);
+            }
+
+            return result;
+        }
+
+        /// <summary>
+        /// 为数据添加单位
+        /// </summary>
+        /// <param name="datatable"></param>
+        /// <returns></returns>
+        public DataTable GetUnitTable(DataTable datatable)
+        {
+            DataTable result = datatable.Copy();
+
+            foreach (DataColumn column in result.Columns)
+            {
+                if (column.ColumnName.Contains("time"))
+                {
+                    column.ColumnName += " 秒";
+                }
+                else if (column.ColumnName.Contains("byte"))
+                {
+                    column.ColumnName += " 字节";
+                }
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// 转换迭代器成字符串
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <returns></returns>
+        private string ParsingIEnumerable(IEnumerable obj)
+        {
+            if (obj.GetType() == typeof(string))
+            {
+                return obj.ToString();
+            }
+            StringBuilder valToString = new StringBuilder();
+            foreach (var i in obj)
+            {
+                Type type = i.GetType();
+                if (type.IsClass)
+                {
+                    if (type == typeof(string))
+                    {
+                        valToString.AppendFormat("{0},", i.ToString());
+                    }
+                    PropertyInfo[] fieldInfo = i.GetType().GetProperties();
+                    if (fieldInfo.Length > 0)
+                    {
+                        foreach (var child in fieldInfo)
+                        {
+                            if (!child.CanRead) continue;
+                            if (child.PropertyType == typeof(string))
+                            {
+                                try
+                                {
+                                    valToString.AppendFormat("{0}={1}{2}", child.Name, child.GetValue(i, null), Environment.NewLine);
+                                }
+                                catch { }
+                            }
+                            else if (child.PropertyType.Namespace.Contains("System.Collections"))
+                            {
+                                valToString.AppendFormat("{0}=List[{2}{1}{2}]{2}", child.Name, ParsingIEnumerable(child.GetValue(i, null) as IEnumerable), Environment.NewLine);
+                            }
+                            else
+                            {
+                                valToString.AppendFormat("{0}={1}{2}", child.Name, child.GetValue(i, null).ToString(), Environment.NewLine);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        valToString.AppendFormat("{0},", i.ToString());
+                    }
+                }
+                else
+                {
+                    valToString.AppendFormat("{0},", i.ToString());
+                }
+            }
+            return valToString.ToString();
+        }
+    }
+}

+ 156 - 0
MyMemcached/DataTraversal.Designer.cs

@@ -0,0 +1,156 @@
+namespace MyMemcached
+{
+    partial class DataTraversal
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DataTraversal));
+            this.cmbSlabs = new System.Windows.Forms.ComboBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.lbItemsCount = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.tbCount = new System.Windows.Forms.TextBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.btnGo = new System.Windows.Forms.Button();
+            this.richTextBox1 = new System.Windows.Forms.RichTextBox();
+            this.progressBar1 = new System.Windows.Forms.ProgressBar();
+            this.SuspendLayout();
+            // 
+            // cmbSlabs
+            // 
+            this.cmbSlabs.FormattingEnabled = true;
+            this.cmbSlabs.Location = new System.Drawing.Point(71, 12);
+            this.cmbSlabs.Name = "cmbSlabs";
+            this.cmbSlabs.Size = new System.Drawing.Size(122, 20);
+            this.cmbSlabs.TabIndex = 0;
+            this.cmbSlabs.SelectedIndexChanged += new System.EventHandler(this.cmbSlabs_SelectedIndexChanged);
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(12, 16);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(53, 12);
+            this.label1.TabIndex = 1;
+            this.label1.Text = "选择区块";
+            // 
+            // lbItemsCount
+            // 
+            this.lbItemsCount.AutoSize = true;
+            this.lbItemsCount.Location = new System.Drawing.Point(216, 16);
+            this.lbItemsCount.Name = "lbItemsCount";
+            this.lbItemsCount.Size = new System.Drawing.Size(0, 12);
+            this.lbItemsCount.TabIndex = 2;
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(23, 45);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(41, 12);
+            this.label2.TabIndex = 3;
+            this.label2.Text = "遍历前";
+            // 
+            // tbCount
+            // 
+            this.tbCount.Location = new System.Drawing.Point(71, 41);
+            this.tbCount.Name = "tbCount";
+            this.tbCount.Size = new System.Drawing.Size(122, 21);
+            this.tbCount.TabIndex = 4;
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(200, 45);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(41, 12);
+            this.label3.TabIndex = 5;
+            this.label3.Text = "条记录";
+            // 
+            // btnGo
+            // 
+            this.btnGo.Location = new System.Drawing.Point(285, 40);
+            this.btnGo.Name = "btnGo";
+            this.btnGo.Size = new System.Drawing.Size(75, 23);
+            this.btnGo.TabIndex = 6;
+            this.btnGo.Text = "获取数据";
+            this.btnGo.UseVisualStyleBackColor = true;
+            this.btnGo.Click += new System.EventHandler(this.btnGo_Click);
+            // 
+            // richTextBox1
+            // 
+            this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.richTextBox1.Location = new System.Drawing.Point(13, 71);
+            this.richTextBox1.Name = "richTextBox1";
+            this.richTextBox1.Size = new System.Drawing.Size(433, 395);
+            this.richTextBox1.TabIndex = 7;
+            this.richTextBox1.Text = "";
+            // 
+            // progressBar1
+            // 
+            this.progressBar1.Location = new System.Drawing.Point(12, 472);
+            this.progressBar1.Name = "progressBar1";
+            this.progressBar1.Size = new System.Drawing.Size(434, 23);
+            this.progressBar1.TabIndex = 8;
+            // 
+            // DataTraversal
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(458, 507);
+            this.Controls.Add(this.progressBar1);
+            this.Controls.Add(this.richTextBox1);
+            this.Controls.Add(this.btnGo);
+            this.Controls.Add(this.label3);
+            this.Controls.Add(this.tbCount);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.lbItemsCount);
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.cmbSlabs);
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.Name = "DataTraversal";
+            this.Text = "数据遍历";
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ComboBox cmbSlabs;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label lbItemsCount;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.TextBox tbCount;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Button btnGo;
+        private System.Windows.Forms.RichTextBox richTextBox1;
+        private System.Windows.Forms.ProgressBar progressBar1;
+    }
+}

+ 127 - 0
MyMemcached/DataTraversal.cs

@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.Threading;
+
+namespace MyMemcached
+{
+    public partial class DataTraversal : Form
+    {
+        DAO.Stats stats = MainForm.Stats;
+        Dictionary<string, object> statSlabs = MainForm.StatSlabs;
+        Dictionary<string, object> statsItems = MainForm.StatsItems;
+        private string Slab { get; set; }
+        private string Count { get; set; }
+
+        public DataTraversal()
+        {
+            InitializeComponent();
+            DataBind();
+        }
+
+        private void DataBind()
+        {
+            foreach (string slab in statSlabs.Keys)
+            {
+                if (slab.Equals("active_slabs") || slab.Equals("total_malloced"))
+                {
+                    continue;
+                }
+                cmbSlabs.Items.Add(slab);
+            }
+            cmbSlabs.SelectedIndex = 0;
+
+            string count = statsItems.ContainsKey(cmbSlabs.SelectedItem.ToString()) ?
+                 ((Dictionary<string, string>)statsItems[cmbSlabs.SelectedItem.ToString()])["number"]
+                 : "0";
+            lbItemsCount.Text = "区块内共有记录: " + count;
+        }
+
+        private void cmbSlabs_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            string count = statsItems.ContainsKey(cmbSlabs.SelectedItem.ToString()) ?
+                 ((Dictionary<string, string>)statsItems[cmbSlabs.SelectedItem.ToString()])["number"]
+                 : "0";
+            lbItemsCount.Text = "区块内共有记录: " + count;
+        }
+
+        private void btnGo_Click(object sender, EventArgs e)
+        {
+            Slab = cmbSlabs.SelectedItem.ToString();
+
+            int count;
+            if (!int.TryParse(tbCount.Text, out count))
+            {
+                MessageBox.Show("查找数目输入错误");
+                return;
+            }
+            Count = count.ToString();
+            richTextBox1.ResetText();
+            progressBar1.Maximum = count;
+            btnGo.Enabled = false;
+
+            Thread thread = new Thread(new ThreadStart(Loop));
+            thread.IsBackground = true;
+            thread.Start();
+        }
+
+
+        private void Loop()
+        {
+            int i = 1;
+            foreach (var cachedump in stats.CacheDump(Servers.CurrentServer, Slab, Count))
+            {
+                var getResult = stats.Get(Servers.CurrentServer, cachedump.Key);
+                SetTextBox(string.Format("Key\t{0} {1}{2}", cachedump.Key, cachedump.Value,Environment.NewLine));
+                if (getResult.ContainsKey("type"))
+                {
+                    SetTextBox(string.Format("Type\t{0}{1}", getResult["type"], Environment.NewLine));
+                }
+                SetTextBox(string.Format("Value{1}{0}{1}{1}", getResult["value"], Environment.NewLine));
+                SetPbValue(i);
+                i++;
+            }
+            SetPbValue(0);
+            this.BeginInvoke(new MethodInvoker(delegate()
+            {
+                btnGo.Enabled = true;
+            }));
+        }
+
+        #region richTextBox1 代理
+        delegate void TextBoxDel(string str);
+
+        private void SetTextBox(string str)
+        {
+            if (richTextBox1.InvokeRequired)
+            {
+                Invoke(new TextBoxDel(SetTextBox), new string[] { str });
+            }
+            else
+            {
+                richTextBox1.AppendText(str);
+            }
+        }
+        #endregion
+
+        #region 进度条代理
+        delegate void pbDelegate(int value);
+
+        private void SetPbValue(int value)
+        {
+            if (progressBar1.InvokeRequired)
+            {
+                Invoke(new pbDelegate(SetPbValue), new object[] { value });
+            }
+            else
+            {
+                progressBar1.Value = value;
+            }
+        }
+        #endregion
+    }
+}

Diff do ficheiro suprimidas por serem muito extensas
+ 6185 - 0
MyMemcached/DataTraversal.resx


+ 113 - 0
MyMemcached/GetForm.Designer.cs

@@ -0,0 +1,113 @@
+namespace MyMemcached
+{
+    partial class GetForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(GetForm));
+            this.label1 = new System.Windows.Forms.Label();
+            this.tbKey = new System.Windows.Forms.TextBox();
+            this.btnGo = new System.Windows.Forms.Button();
+            this.textBox1 = new System.Windows.Forms.TextBox();
+            this.btn_delCache = new System.Windows.Forms.Button();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(13, 17);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(23, 12);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Key";
+            // 
+            // tbKey
+            // 
+            this.tbKey.Location = new System.Drawing.Point(43, 13);
+            this.tbKey.Name = "tbKey";
+            this.tbKey.Size = new System.Drawing.Size(290, 21);
+            this.tbKey.TabIndex = 1;
+            this.tbKey.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tbKey_KeyDown);
+            // 
+            // btnGo
+            // 
+            this.btnGo.Location = new System.Drawing.Point(340, 13);
+            this.btnGo.Name = "btnGo";
+            this.btnGo.Size = new System.Drawing.Size(75, 23);
+            this.btnGo.TabIndex = 2;
+            this.btnGo.Text = "查询";
+            this.btnGo.UseVisualStyleBackColor = true;
+            this.btnGo.Click += new System.EventHandler(this.btnGo_Click);
+            // 
+            // textBox1
+            // 
+            this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.textBox1.Location = new System.Drawing.Point(15, 53);
+            this.textBox1.Multiline = true;
+            this.textBox1.Name = "textBox1";
+            this.textBox1.Size = new System.Drawing.Size(431, 423);
+            this.textBox1.TabIndex = 3;
+            // 
+            // btn_delCache
+            // 
+            this.btn_delCache.Location = new System.Drawing.Point(185, 482);
+            this.btn_delCache.Name = "btn_delCache";
+            this.btn_delCache.Size = new System.Drawing.Size(75, 23);
+            this.btn_delCache.TabIndex = 4;
+            this.btn_delCache.Text = "删除该缓存";
+            this.btn_delCache.UseVisualStyleBackColor = true;
+            this.btn_delCache.Click += new System.EventHandler(this.btn_delCache_Click);
+            // 
+            // GetForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(458, 507);
+            this.Controls.Add(this.btn_delCache);
+            this.Controls.Add(this.textBox1);
+            this.Controls.Add(this.btnGo);
+            this.Controls.Add(this.tbKey);
+            this.Controls.Add(this.label1);
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.Name = "GetForm";
+            this.Text = "查询";
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.TextBox tbKey;
+        private System.Windows.Forms.Button btnGo;
+        private System.Windows.Forms.TextBox textBox1;
+        private System.Windows.Forms.Button btn_delCache;
+    }
+}

+ 51 - 0
MyMemcached/GetForm.cs

@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+namespace MyMemcached
+{
+    public partial class GetForm : Form
+    {
+        DAO.Stats stats = MainForm.Stats;
+        public GetForm()
+        {
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// 开始查询
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void btnGo_Click(object sender, EventArgs e)
+        {
+            textBox1.ResetText();
+            var getResult = stats.Get(Servers.CurrentServer,tbKey.Text);
+            textBox1.AppendText(string.Format("Value\t{0}\r\n", getResult["value"]));
+            if (getResult.ContainsKey("type"))
+            {
+                textBox1.AppendText(string.Format("Type\t{0}\r\n", getResult["type"]));
+            }
+        }
+
+        private void tbKey_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyValue == 13)
+            {
+                btnGo_Click(sender, e);
+            }
+        }
+
+        private void btn_delCache_Click(object sender, EventArgs e)
+        {
+            if (string.IsNullOrEmpty(tbKey.Text)) return;
+
+            textBox1.ResetText();
+            textBox1.AppendText(stats.Delete(Servers.CurrentServer, tbKey.Text));
+        }
+    }
+}

Diff do ficheiro suprimidas por serem muito extensas
+ 6185 - 0
MyMemcached/GetForm.resx


BIN
MyMemcached/Lib/Enyim.Caching.dll


+ 514 - 0
MyMemcached/MainForm.Designer.cs

@@ -0,0 +1,514 @@
+namespace MyMemcached
+{
+    partial class MainForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.btnAddServer = new System.Windows.Forms.Button();
+            this.tbPort = new System.Windows.Forms.TextBox();
+            this.label2 = new System.Windows.Forms.Label();
+            this.label1 = new System.Windows.Forms.Label();
+            this.tbHost = new System.Windows.Forms.TextBox();
+            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+            this.菜单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.telnetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.重置ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.statsResetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.flushallToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.refreshToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.DataTraversalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.getToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.dataGridView1 = new System.Windows.Forms.DataGridView();
+            this.ServerList = new System.Windows.Forms.ListBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.itemsview = new System.Windows.Forms.TextBox();
+            this.slabView = new System.Windows.Forms.TextBox();
+            this.label4 = new System.Windows.Forms.Label();
+            this.cmbSlabs = new System.Windows.Forms.ComboBox();
+            this.lbTotalMalloced = new System.Windows.Forms.Label();
+            this.lbActiveSlabs = new System.Windows.Forms.Label();
+            this.panel2 = new System.Windows.Forms.Panel();
+            this.pbCAS = new System.Windows.Forms.ProgressBar();
+            this.label10 = new System.Windows.Forms.Label();
+            this.pbDecr = new System.Windows.Forms.ProgressBar();
+            this.label9 = new System.Windows.Forms.Label();
+            this.pbIncr = new System.Windows.Forms.ProgressBar();
+            this.label8 = new System.Windows.Forms.Label();
+            this.pbDelete = new System.Windows.Forms.ProgressBar();
+            this.label7 = new System.Windows.Forms.Label();
+            this.pbget = new System.Windows.Forms.ProgressBar();
+            this.label6 = new System.Windows.Forms.Label();
+            this.label5 = new System.Windows.Forms.Label();
+            this.pbbytes = new System.Windows.Forms.ProgressBar();
+            this.groupBox1.SuspendLayout();
+            this.menuStrip1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
+            this.panel1.SuspendLayout();
+            this.panel2.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.AccessibleDescription = "";
+            this.groupBox1.AccessibleName = "";
+            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.groupBox1.Controls.Add(this.btnAddServer);
+            this.groupBox1.Controls.Add(this.tbPort);
+            this.groupBox1.Controls.Add(this.label2);
+            this.groupBox1.Controls.Add(this.label1);
+            this.groupBox1.Controls.Add(this.tbHost);
+            this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.groupBox1.Location = new System.Drawing.Point(706, 27);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(200, 121);
+            this.groupBox1.TabIndex = 0;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "添加服务器";
+            // 
+            // btnAddServer
+            // 
+            this.btnAddServer.Location = new System.Drawing.Point(57, 92);
+            this.btnAddServer.Name = "btnAddServer";
+            this.btnAddServer.Size = new System.Drawing.Size(75, 23);
+            this.btnAddServer.TabIndex = 4;
+            this.btnAddServer.Text = "添加";
+            this.btnAddServer.UseVisualStyleBackColor = true;
+            this.btnAddServer.Click += new System.EventHandler(this.btnAddServer_Click);
+            // 
+            // tbPort
+            // 
+            this.tbPort.Location = new System.Drawing.Point(42, 51);
+            this.tbPort.Name = "tbPort";
+            this.tbPort.Size = new System.Drawing.Size(147, 21);
+            this.tbPort.TabIndex = 3;
+            this.tbPort.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tbPort_KeyDown);
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(6, 60);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(29, 12);
+            this.label2.TabIndex = 2;
+            this.label2.Text = "端口";
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(7, 30);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(17, 12);
+            this.label1.TabIndex = 1;
+            this.label1.Text = "IP";
+            // 
+            // tbHost
+            // 
+            this.tbHost.Location = new System.Drawing.Point(42, 21);
+            this.tbHost.Name = "tbHost";
+            this.tbHost.Size = new System.Drawing.Size(147, 21);
+            this.tbHost.TabIndex = 0;
+            this.tbHost.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tbHost_KeyDown);
+            // 
+            // menuStrip1
+            // 
+            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.菜单ToolStripMenuItem,
+            this.refreshToolStripMenuItem,
+            this.数据ToolStripMenuItem});
+            this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+            this.menuStrip1.Name = "menuStrip1";
+            this.menuStrip1.Size = new System.Drawing.Size(906, 24);
+            this.menuStrip1.TabIndex = 2;
+            this.menuStrip1.Text = "menuStrip1";
+            // 
+            // 菜单ToolStripMenuItem
+            // 
+            this.菜单ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.telnetToolStripMenuItem,
+            this.重置ToolStripMenuItem});
+            this.菜单ToolStripMenuItem.Name = "菜单ToolStripMenuItem";
+            this.菜单ToolStripMenuItem.Size = new System.Drawing.Size(43, 20);
+            this.菜单ToolStripMenuItem.Text = "菜单";
+            // 
+            // telnetToolStripMenuItem
+            // 
+            this.telnetToolStripMenuItem.Name = "telnetToolStripMenuItem";
+            this.telnetToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
+            this.telnetToolStripMenuItem.Text = "telnet 命令行";
+            this.telnetToolStripMenuItem.Click += new System.EventHandler(this.telnetToolStripMenuItem_Click);
+            // 
+            // 重置ToolStripMenuItem
+            // 
+            this.重置ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.statsResetToolStripMenuItem,
+            this.flushallToolStripMenuItem});
+            this.重置ToolStripMenuItem.Name = "重置ToolStripMenuItem";
+            this.重置ToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
+            this.重置ToolStripMenuItem.Text = "重置";
+            // 
+            // statsResetToolStripMenuItem
+            // 
+            this.statsResetToolStripMenuItem.Name = "statsResetToolStripMenuItem";
+            this.statsResetToolStripMenuItem.Size = new System.Drawing.Size(134, 22);
+            this.statsResetToolStripMenuItem.Text = "stats reset";
+            this.statsResetToolStripMenuItem.Click += new System.EventHandler(this.statsResetToolStripMenuItem_Click);
+            // 
+            // flushallToolStripMenuItem
+            // 
+            this.flushallToolStripMenuItem.Name = "flushallToolStripMenuItem";
+            this.flushallToolStripMenuItem.Size = new System.Drawing.Size(134, 22);
+            this.flushallToolStripMenuItem.Text = "flush_all";
+            this.flushallToolStripMenuItem.Click += new System.EventHandler(this.flushallToolStripMenuItem_Click);
+            // 
+            // refreshToolStripMenuItem
+            // 
+            this.refreshToolStripMenuItem.Name = "refreshToolStripMenuItem";
+            this.refreshToolStripMenuItem.Size = new System.Drawing.Size(43, 20);
+            this.refreshToolStripMenuItem.Text = "刷新";
+            this.refreshToolStripMenuItem.Click += new System.EventHandler(this.refreshToolStripMenuItem_Click);
+            // 
+            // 数据ToolStripMenuItem
+            // 
+            this.数据ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.DataTraversalToolStripMenuItem,
+            this.getToolStripMenuItem});
+            this.数据ToolStripMenuItem.Name = "数据ToolStripMenuItem";
+            this.数据ToolStripMenuItem.Size = new System.Drawing.Size(43, 20);
+            this.数据ToolStripMenuItem.Text = "数据";
+            // 
+            // DataTraversalToolStripMenuItem
+            // 
+            this.DataTraversalToolStripMenuItem.Name = "DataTraversalToolStripMenuItem";
+            this.DataTraversalToolStripMenuItem.Size = new System.Drawing.Size(122, 22);
+            this.DataTraversalToolStripMenuItem.Text = "数据遍历";
+            this.DataTraversalToolStripMenuItem.Click += new System.EventHandler(this.DataTraversalToolStripMenuItem_Click);
+            // 
+            // getToolStripMenuItem
+            // 
+            this.getToolStripMenuItem.Name = "getToolStripMenuItem";
+            this.getToolStripMenuItem.Size = new System.Drawing.Size(122, 22);
+            this.getToolStripMenuItem.Text = "Get";
+            this.getToolStripMenuItem.Click += new System.EventHandler(this.getToolStripMenuItem_Click);
+            // 
+            // dataGridView1
+            // 
+            this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.dataGridView1.Location = new System.Drawing.Point(20, 36);
+            this.dataGridView1.Name = "dataGridView1";
+            this.dataGridView1.RowTemplate.Height = 23;
+            this.dataGridView1.Size = new System.Drawing.Size(680, 169);
+            this.dataGridView1.TabIndex = 3;
+            // 
+            // ServerList
+            // 
+            this.ServerList.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.ServerList.FormattingEnabled = true;
+            this.ServerList.ItemHeight = 12;
+            this.ServerList.Location = new System.Drawing.Point(706, 211);
+            this.ServerList.Name = "ServerList";
+            this.ServerList.Size = new System.Drawing.Size(189, 220);
+            this.ServerList.TabIndex = 4;
+            this.ServerList.SelectedIndexChanged += new System.EventHandler(this.ServerList_SelectedIndexChanged);
+            // 
+            // label3
+            // 
+            this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(704, 193);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(65, 12);
+            this.label3.TabIndex = 5;
+            this.label3.Text = "服务器列表";
+            // 
+            // panel1
+            // 
+            this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.panel1.Controls.Add(this.itemsview);
+            this.panel1.Controls.Add(this.slabView);
+            this.panel1.Controls.Add(this.label4);
+            this.panel1.Controls.Add(this.cmbSlabs);
+            this.panel1.Controls.Add(this.lbTotalMalloced);
+            this.panel1.Controls.Add(this.lbActiveSlabs);
+            this.panel1.Location = new System.Drawing.Point(20, 211);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(680, 220);
+            this.panel1.TabIndex = 6;
+            // 
+            // itemsview
+            // 
+            this.itemsview.Location = new System.Drawing.Point(335, 35);
+            this.itemsview.Multiline = true;
+            this.itemsview.Name = "itemsview";
+            this.itemsview.ReadOnly = true;
+            this.itemsview.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+            this.itemsview.Size = new System.Drawing.Size(273, 173);
+            this.itemsview.TabIndex = 5;
+            // 
+            // slabView
+            // 
+            this.slabView.Location = new System.Drawing.Point(6, 31);
+            this.slabView.Multiline = true;
+            this.slabView.Name = "slabView";
+            this.slabView.ReadOnly = true;
+            this.slabView.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+            this.slabView.Size = new System.Drawing.Size(272, 178);
+            this.slabView.TabIndex = 4;
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Location = new System.Drawing.Point(405, 5);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(77, 12);
+            this.label4.TabIndex = 3;
+            this.label4.Text = "选择内存区块";
+            // 
+            // cmbSlabs
+            // 
+            this.cmbSlabs.FormattingEnabled = true;
+            this.cmbSlabs.Location = new System.Drawing.Point(488, 2);
+            this.cmbSlabs.Name = "cmbSlabs";
+            this.cmbSlabs.Size = new System.Drawing.Size(121, 20);
+            this.cmbSlabs.TabIndex = 2;
+            this.cmbSlabs.SelectedIndexChanged += new System.EventHandler(this.cmbSlabs_SelectedIndexChanged);
+            // 
+            // lbTotalMalloced
+            // 
+            this.lbTotalMalloced.AutoSize = true;
+            this.lbTotalMalloced.Location = new System.Drawing.Point(149, 5);
+            this.lbTotalMalloced.Name = "lbTotalMalloced";
+            this.lbTotalMalloced.Size = new System.Drawing.Size(0, 12);
+            this.lbTotalMalloced.TabIndex = 1;
+            // 
+            // lbActiveSlabs
+            // 
+            this.lbActiveSlabs.AutoSize = true;
+            this.lbActiveSlabs.Location = new System.Drawing.Point(4, 5);
+            this.lbActiveSlabs.Name = "lbActiveSlabs";
+            this.lbActiveSlabs.Size = new System.Drawing.Size(0, 12);
+            this.lbActiveSlabs.TabIndex = 0;
+            // 
+            // panel2
+            // 
+            this.panel2.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.panel2.Controls.Add(this.pbCAS);
+            this.panel2.Controls.Add(this.label10);
+            this.panel2.Controls.Add(this.pbDecr);
+            this.panel2.Controls.Add(this.label9);
+            this.panel2.Controls.Add(this.pbIncr);
+            this.panel2.Controls.Add(this.label8);
+            this.panel2.Controls.Add(this.pbDelete);
+            this.panel2.Controls.Add(this.label7);
+            this.panel2.Controls.Add(this.pbget);
+            this.panel2.Controls.Add(this.label6);
+            this.panel2.Controls.Add(this.label5);
+            this.panel2.Controls.Add(this.pbbytes);
+            this.panel2.Location = new System.Drawing.Point(20, 437);
+            this.panel2.Name = "panel2";
+            this.panel2.Size = new System.Drawing.Size(874, 85);
+            this.panel2.TabIndex = 7;
+            // 
+            // pbCAS
+            // 
+            this.pbCAS.Location = new System.Drawing.Point(651, 48);
+            this.pbCAS.Name = "pbCAS";
+            this.pbCAS.Size = new System.Drawing.Size(201, 23);
+            this.pbCAS.TabIndex = 11;
+            // 
+            // label10
+            // 
+            this.label10.AutoSize = true;
+            this.label10.Location = new System.Drawing.Point(586, 53);
+            this.label10.Name = "label10";
+            this.label10.Size = new System.Drawing.Size(59, 12);
+            this.label10.TabIndex = 10;
+            this.label10.Text = "CAS命中率";
+            // 
+            // pbDecr
+            // 
+            this.pbDecr.Location = new System.Drawing.Point(361, 48);
+            this.pbDecr.Name = "pbDecr";
+            this.pbDecr.Size = new System.Drawing.Size(201, 23);
+            this.pbDecr.TabIndex = 9;
+            // 
+            // label9
+            // 
+            this.label9.AutoSize = true;
+            this.label9.Location = new System.Drawing.Point(290, 53);
+            this.label9.Name = "label9";
+            this.label9.Size = new System.Drawing.Size(65, 12);
+            this.label9.TabIndex = 8;
+            this.label9.Text = "Decr命中率";
+            // 
+            // pbIncr
+            // 
+            this.pbIncr.Location = new System.Drawing.Point(75, 48);
+            this.pbIncr.Name = "pbIncr";
+            this.pbIncr.Size = new System.Drawing.Size(201, 23);
+            this.pbIncr.TabIndex = 7;
+            // 
+            // label8
+            // 
+            this.label8.AutoSize = true;
+            this.label8.Location = new System.Drawing.Point(4, 53);
+            this.label8.Name = "label8";
+            this.label8.Size = new System.Drawing.Size(65, 12);
+            this.label8.TabIndex = 6;
+            this.label8.Text = "Incr命中率";
+            // 
+            // pbDelete
+            // 
+            this.pbDelete.Location = new System.Drawing.Point(651, 3);
+            this.pbDelete.Name = "pbDelete";
+            this.pbDelete.Size = new System.Drawing.Size(201, 23);
+            this.pbDelete.TabIndex = 5;
+            // 
+            // label7
+            // 
+            this.label7.AutoSize = true;
+            this.label7.Location = new System.Drawing.Point(568, 8);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(77, 12);
+            this.label7.TabIndex = 4;
+            this.label7.Text = "Delete命中率";
+            // 
+            // pbget
+            // 
+            this.pbget.Location = new System.Drawing.Point(361, 3);
+            this.pbget.Name = "pbget";
+            this.pbget.Size = new System.Drawing.Size(201, 23);
+            this.pbget.TabIndex = 3;
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Location = new System.Drawing.Point(284, 8);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(71, 12);
+            this.label6.TabIndex = 2;
+            this.label6.Text = "Get的命中率";
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Location = new System.Drawing.Point(16, 8);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(53, 12);
+            this.label5.TabIndex = 1;
+            this.label5.Text = "已用内存";
+            // 
+            // pbbytes
+            // 
+            this.pbbytes.Location = new System.Drawing.Point(75, 3);
+            this.pbbytes.Name = "pbbytes";
+            this.pbbytes.Size = new System.Drawing.Size(201, 23);
+            this.pbbytes.TabIndex = 0;
+            // 
+            // MainForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(906, 528);
+            this.Controls.Add(this.panel2);
+            this.Controls.Add(this.panel1);
+            this.Controls.Add(this.label3);
+            this.Controls.Add(this.ServerList);
+            this.Controls.Add(this.dataGridView1);
+            this.Controls.Add(this.groupBox1);
+            this.Controls.Add(this.menuStrip1);
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.MainMenuStrip = this.menuStrip1;
+            this.Name = "MainForm";
+            this.Text = "能龙 memcached 缓存监控工具";
+            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.menuStrip1.ResumeLayout(false);
+            this.menuStrip1.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
+            this.panel1.ResumeLayout(false);
+            this.panel1.PerformLayout();
+            this.panel2.ResumeLayout(false);
+            this.panel2.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox groupBox1;
+        private System.Windows.Forms.Button btnAddServer;
+        private System.Windows.Forms.TextBox tbPort;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.TextBox tbHost;
+        private System.Windows.Forms.MenuStrip menuStrip1;
+        private System.Windows.Forms.ToolStripMenuItem 菜单ToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem telnetToolStripMenuItem;
+        private System.Windows.Forms.DataGridView dataGridView1;
+        private System.Windows.Forms.ListBox ServerList;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.Label lbTotalMalloced;
+        private System.Windows.Forms.Label lbActiveSlabs;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.ComboBox cmbSlabs;
+        private System.Windows.Forms.Panel panel2;
+        private System.Windows.Forms.ProgressBar pbget;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.ProgressBar pbbytes;
+        private System.Windows.Forms.TextBox slabView;
+        private System.Windows.Forms.ToolStripMenuItem 重置ToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem statsResetToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem flushallToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem refreshToolStripMenuItem;
+        private System.Windows.Forms.TextBox itemsview;
+        private System.Windows.Forms.ToolStripMenuItem 数据ToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem DataTraversalToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem getToolStripMenuItem;
+        private System.Windows.Forms.ProgressBar pbCAS;
+        private System.Windows.Forms.Label label10;
+        private System.Windows.Forms.ProgressBar pbDecr;
+        private System.Windows.Forms.Label label9;
+        private System.Windows.Forms.ProgressBar pbIncr;
+        private System.Windows.Forms.Label label8;
+        private System.Windows.Forms.ProgressBar pbDelete;
+        private System.Windows.Forms.Label label7;
+    }
+}

+ 258 - 0
MyMemcached/MainForm.cs

@@ -0,0 +1,258 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.Net.Sockets;
+
+
+namespace MyMemcached
+{
+    public partial class MainForm : Form
+    {
+        private static DAO.Stats stats = new DAO.Stats();
+        private static Dictionary<string, object> statSlabs;
+        private static Dictionary<string, object> statsItems;
+
+        public static DAO.Stats Stats { get { return stats; } }
+        public static Dictionary<string, object> StatSlabs { get { return statSlabs; } }
+        public static Dictionary<string, object> StatsItems { get { return statsItems; } }
+
+
+        public MainForm()
+        {
+            InitializeComponent();
+            this.Focus();
+            var servers = System.Configuration.ConfigurationManager.AppSettings["servers"].Split(',');
+            AddServers(servers);
+        }
+        /// <summary>
+        /// 打开telnet命令行
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void telnetToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            TelnetCmd telnetCmd = new TelnetCmd();
+            telnetCmd.Show();
+            telnetCmd.Activate();
+        }
+
+        private void btnAddServer_Click(object sender, EventArgs e)
+        {
+            AddServers(new string[] { string.Format("{0}:{1}", tbHost.Text, tbPort.Text) });
+        }
+
+        private void tbPort_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyValue == 13)
+            {
+                btnAddServer_Click(sender, e);
+            }
+        }
+
+        private void tbHost_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyValue == 13)
+            {
+                btnAddServer_Click(sender, e);
+            }
+        }
+
+        private void ServerList_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (ServerList.SelectedItem == null)
+            {
+                return;
+            }
+            Servers.CurrentServer = Servers.ServerList[ServerList.SelectedItem.ToString()];
+            DataBind();
+        }
+        private void cmbSlabs_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            SlabsInfoBind(statSlabs, statsItems);
+        }
+
+        private void DataBind()
+        {
+            if (ServerList.SelectedItem == null)
+            {
+                return;
+            }
+            statSlabs = stats.StatSlabs(Servers.CurrentServer);
+            statsItems = stats.StatsItems(Servers.CurrentServer);
+            cmbSlabs.ResetText();
+            cmbSlabs.Items.Clear();
+            foreach (string slab in statSlabs.Keys)
+            {
+                if (slab.Equals("active_slabs") || slab.Equals("total_malloced"))
+                {
+                    continue;
+                }
+                cmbSlabs.Items.Add(slab);
+            }
+
+            ProgressDataBind();
+
+            if (cmbSlabs.Items.Count > 0)
+            {
+                cmbSlabs.SelectedIndex = 0;
+            }
+            SlabsInfoBind(statSlabs, statsItems);
+        }
+
+        //绑定进度条数据
+        private void ProgressDataBind()
+        {
+            if (ServerList.SelectedItem == null)
+            {
+                return;
+            }
+            DataRow serverStats = stats.AllServerStats.Rows.Find(ServerList.SelectedItem.ToString());
+
+            pbbytes.Maximum = Convert.ToInt32(serverStats["limit_maxbytes"]);
+            pbbytes.Value = Convert.ToInt32(serverStats["bytes"]);
+
+            pbget.Maximum = Convert.ToInt32(serverStats["cmd_get"]);
+            pbget.Value = Convert.ToInt32(serverStats["get_hits"]);
+
+            pbDelete.Maximum = Convert.ToInt32(serverStats["delete_hits"]) +
+                Convert.ToInt32(serverStats["delete_misses"]);
+            pbDelete.Value = Convert.ToInt32(serverStats["delete_hits"]);
+
+            pbIncr.Maximum = Convert.ToInt32(serverStats["incr_hits"]) +
+                Convert.ToInt32(serverStats["incr_misses"]);
+            pbIncr.Value = Convert.ToInt32(serverStats["incr_hits"]);
+
+            pbDecr.Maximum = Convert.ToInt32(serverStats["decr_hits"]) +
+                Convert.ToInt32(serverStats["decr_misses"]);
+            pbDecr.Value = Convert.ToInt32(serverStats["decr_hits"]);
+
+            pbCAS.Maximum = Convert.ToInt32(serverStats["cas_hits"]) +
+                Convert.ToInt32(serverStats["cas_misses"]);
+            pbCAS.Value = Convert.ToInt32(serverStats["cas_hits"]);
+        }
+
+        //textbox数据绑定
+        private void SlabsInfoBind(Dictionary<string, object> statSlabs, Dictionary<string, object> statsItems)
+        {
+            lbActiveSlabs.Text = "slab数量: " + statSlabs["active_slabs"].ToString();
+            lbTotalMalloced.Text = "总内存数量: " + statSlabs["total_malloced"].ToString() + " 字节";
+
+            slabView.ResetText();
+            itemsview.ResetText();
+            if (cmbSlabs.Items.Count <= 0)
+            { return; }
+
+            foreach (var slabinfo in (Dictionary<string, string>)statSlabs[cmbSlabs.SelectedItem.ToString()])
+            {
+                slabView.Text += string.Format("{0}:\t{1}\r\n", slabinfo.Key, slabinfo.Value);
+            }
+
+            if (!statsItems.ContainsKey(cmbSlabs.SelectedItem.ToString()))
+            {
+                return;
+            }
+            foreach (var itemsinfo in (Dictionary<string, string>)statsItems[cmbSlabs.SelectedItem.ToString()])
+            {
+                itemsview.AppendText(string.Format("{0}:\t{1}\r\n", itemsinfo.Key, itemsinfo.Value));
+            }
+        }
+
+        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            dataGridView1.DataSource = stats.GetUnitTable(stats.GetAllServerStats());
+            DataBind();
+        }
+
+        private void statsResetToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            string message = string.Format("重置{0}:{1}的状态?", Servers.CurrentServer.Hostname, Servers.CurrentServer.Port);
+            if (MessageBox.Show(message, "Reset", MessageBoxButtons.OKCancel) == DialogResult.OK)
+            {
+                if (stats.StatsReset(Servers.CurrentServer))
+                {
+                    refreshToolStripMenuItem_Click(sender, e);
+                }
+            }
+        }
+
+        private void flushallToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            string message = string.Format("清空{0}:{1}所有的缓存?", Servers.CurrentServer.Hostname, Servers.CurrentServer.Port);
+            if (MessageBox.Show(message, "Flush_ALL", MessageBoxButtons.OKCancel) == DialogResult.OK)
+            {
+                if (stats.FlushAll(Servers.CurrentServer))
+                {
+                    refreshToolStripMenuItem_Click(sender, e);
+                }
+            }
+        }
+
+        private void DataTraversalToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (statSlabs == null)
+            {
+                MessageBox.Show("请选择服务器");
+                return;
+            }
+            DataTraversal dataTraversal = new DataTraversal();
+            dataTraversal.Show();
+            dataTraversal.Activate();
+        }
+
+        private void getToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (statSlabs == null)
+            {
+                MessageBox.Show("请选择服务器");
+                return;
+            }
+            GetForm getForm = new GetForm();
+            getForm.Show();
+            getForm.Activate();
+        }
+
+        private void AddServers(string[] servers)
+        {
+            try
+            {
+                foreach (string server in servers)
+                {
+                    try
+                    {
+                        string[] val = server.Split(':');
+                        TelnetConnection telnet = new TelnetConnection(val[0].Trim(), Convert.ToInt32(val[1].Trim()));
+                        Servers.Add(telnet);
+                        ServerList.Items.Add(string.Format("{0}:{1}", telnet.Hostname, telnet.Port));
+                    }
+                    catch (Exception ex)
+                    {
+                        MessageBox.Show(ex.Message);
+                    }
+                }
+                dataGridView1.DataSource = stats.GetUnitTable(stats.GetAllServerStats());
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.Message);
+            }
+        }
+
+        //程序退出
+        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            foreach (var client in MyMemcached.DAO.Stats.MClientList)
+            {
+                client.Value.Dispose();
+            }
+
+            foreach (var server in MyMemcached.Servers.ServerList)
+            {
+                server.Value.DisConnect();
+            }
+        }
+    }
+}

Diff do ficheiro suprimidas por serem muito extensas
+ 6188 - 0
MyMemcached/MainForm.resx


+ 127 - 0
MyMemcached/MyMemcached.csproj

@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{12B4613A-9C5B-4590-AC69-AF5FA090C37B}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>MyMemcached</RootNamespace>
+    <AssemblyName>MyMemcached</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>25.ico</ApplicationIcon>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Enyim.Caching">
+      <HintPath>Lib\Enyim.Caching.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.configuration" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="DataTraversal.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="DataTraversal.Designer.cs">
+      <DependentUpon>DataTraversal.cs</DependentUpon>
+    </Compile>
+    <Compile Include="GetForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="GetForm.Designer.cs">
+      <DependentUpon>GetForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="MainForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="MainForm.Designer.cs">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DAO\Stats.cs" />
+    <Compile Include="mcacheClientExt.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Servers.cs" />
+    <Compile Include="Telnet.cs" />
+    <Compile Include="TelnetCmd.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="TelnetCmd.Designer.cs">
+      <DependentUpon>TelnetCmd.cs</DependentUpon>
+    </Compile>
+    <EmbeddedResource Include="DataTraversal.resx">
+      <DependentUpon>DataTraversal.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="GetForm.resx">
+      <DependentUpon>GetForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="MainForm.resx">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+      <DesignTime>True</DesignTime>
+    </Compile>
+    <EmbeddedResource Include="TelnetCmd.resx">
+      <DependentUpon>TelnetCmd.cs</DependentUpon>
+    </EmbeddedResource>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="25.ico" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 20 - 0
MyMemcached/Program.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+namespace MyMemcached
+{
+    static class Program
+    {
+        /// <summary>
+        /// 应用程序的主入口点。
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new MainForm());
+        }
+    }
+}

+ 36 - 0
MyMemcached/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的常规信息通过以下
+// 特性集控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("MyMemcached")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MyMemcached")]
+[assembly: AssemblyCopyright("Copyright ©  2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 使此程序集中的类型
+// 对 COM 组件不可见。  如果需要从 COM 访问此程序集中的类型,
+// 则将该类型上的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("9facde71-54a8-4951-85a7-0d1db25afe52")]
+
+// 程序集的版本信息由下面四个值组成: 
+//
+//      主版本
+//      次版本 
+//      生成号
+//      修订号
+//
+// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”: 
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]

+ 63 - 0
MyMemcached/Properties/Resources.Designer.cs

@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     此代码由工具生成。
+//     运行时版本:4.0.30319.18449
+//
+//     对此文件的更改可能会导致不正确的行为,并且如果
+//     重新生成代码,这些更改将会丢失。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace MyMemcached.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   一个强类型的资源类,用于查找本地化的字符串等。
+    /// </summary>
+    // 此类是由 StronglyTypedResourceBuilder
+    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+    // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+    // (以 /str 作为命令选项),或重新生成 VS 项目。
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   返回此类使用的缓存的 ResourceManager 实例。
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MyMemcached.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   使用此强类型资源类,为所有资源查找
+        ///   重写当前线程的 CurrentUICulture 属性。
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}

+ 117 - 0
MyMemcached/Properties/Resources.resx

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 26 - 0
MyMemcached/Properties/Settings.Designer.cs

@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     此代码由工具生成。
+//     运行时版本:4.0.30319.18449
+//
+//     对此文件的更改可能会导致不正确的行为,并且如果
+//     重新生成代码,这些更改将会丢失。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace MyMemcached.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+    }
+}

+ 7 - 0
MyMemcached/Properties/Settings.settings

@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>

+ 43 - 0
MyMemcached/Servers.cs

@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MyMemcached
+{
+    public static class Servers
+    {
+        public static TelnetConnection CurrentServer { get; set; }
+
+        /// <summary>
+        /// telnet 服务器列表
+        /// </summary>
+        private static Dictionary<string, TelnetConnection> _serverList;
+        public static Dictionary<string, TelnetConnection> ServerList 
+        {
+            get 
+            {
+                if (_serverList==null)
+                {
+                    _serverList = new Dictionary<string, TelnetConnection>();
+                }
+                return _serverList;
+            }
+        }
+
+
+        /// <summary>
+        /// 添加服务器
+        /// </summary>
+        /// <param name="telnet"></param>
+        public static void Add(TelnetConnection telnet)
+        {
+            if (_serverList == null)
+            {
+                _serverList = new Dictionary<string, TelnetConnection>();
+            }
+            string server=string.Format("{0}:{1}", telnet.Hostname, telnet.Port);
+            _serverList.Add(server, telnet);
+          // CurrentServer = _serverList[server];
+        }
+    }
+}

+ 149 - 0
MyMemcached/Telnet.cs

@@ -0,0 +1,149 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Net.Sockets;
+
+namespace MyMemcached
+{
+    enum Verbs
+    {
+        WILL = 251,
+        WONT = 252,
+        DO = 253,
+        DONT = 254,
+        IAC = 255
+    }
+
+    enum Options
+    {
+        SGA = 3
+    }
+
+    public class TelnetConnection
+    {
+         TcpClient tcpSocket;
+
+         int TimeOut = 1;
+
+         public string Hostname { get; set; }
+         public int Port { get; set; }
+
+        public TelnetConnection(String Hostname, int Port)
+        {
+            tcpSocket = new TcpClient(Hostname, Port);
+            this.Hostname = Hostname;
+            this.Port = Port;
+        }
+
+        public void DisConnect()
+        {
+            if (tcpSocket != null)
+            {
+                if (tcpSocket.Connected)
+                {
+                    tcpSocket.Client.Disconnect(true);
+                }
+            }
+        }
+
+        public void WriteLine(string cmd)
+        {
+            Write(cmd + "\r\n");
+        }
+
+        public void Write(string cmd)
+        {
+            if (!tcpSocket.Connected) return;
+            byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(cmd.Replace("\0xFF", "\0xFF\0xFF"));
+            tcpSocket.GetStream().Write(buf, 0, buf.Length);
+        }
+
+        public string Read()
+        {
+            if (!tcpSocket.Connected) return null;
+            StringBuilder sb = new StringBuilder();
+
+            //设置超时
+            DateTime timeout = DateTime.Now.AddSeconds(TimeOut);
+            while (tcpSocket.Available<=0)
+            {
+                if (DateTime.Now.CompareTo(timeout)>0)
+                    break;
+            }
+            
+            while (tcpSocket.Available > 0 )
+            {
+                ParseTelnet(sb);
+            }
+           
+            return ConvertToGB2312(sb.ToString());
+        }
+
+        public bool IsConnected
+        {
+            get { return tcpSocket.Connected; }
+        }
+
+        /// <summary>
+        /// 将TCP/IP协议转换成Telnet协议
+        /// </summary>
+        /// <param name="sb"></param>
+        private void ParseTelnet(StringBuilder sb)
+        {
+            while (tcpSocket.Available > 0)
+            {
+                int input = tcpSocket.GetStream().ReadByte();
+                switch (input)
+                {
+                    case -1:
+                        break;
+                    case (int)Verbs.IAC:
+                        // interpret as command  
+                        int inputverb = tcpSocket.GetStream().ReadByte();
+                        if (inputverb == -1) break;
+                        switch (inputverb)
+                        {
+                            case (int)Verbs.IAC:
+                                //literal IAC = 255 escaped, so append char 255 to string  
+                                sb.Append(inputverb);
+                                break;
+                            case (int)Verbs.DO:
+                            case (int)Verbs.DONT:
+                            case (int)Verbs.WILL:
+                            case (int)Verbs.WONT:
+                                // reply to all commands with "WONT", unless it is SGA (suppres go ahead)  
+                                int inputoption = tcpSocket.GetStream().ReadByte();
+                                if (inputoption == -1) break;
+                                tcpSocket.GetStream().WriteByte((byte)Verbs.IAC);
+                                if (inputoption == (int)Options.SGA)
+                                    tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WILL : (byte)Verbs.DO);
+                                else
+                                    tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WONT : (byte)Verbs.DONT);
+                                tcpSocket.GetStream().WriteByte((byte)inputoption);
+                                break;
+                            default:
+                                break;
+                        }
+                        break;
+                    default:
+                        sb.Append((char)input);
+                        break;
+                }
+            }
+        }
+
+        private string ConvertToGB2312(string str_origin)
+        {
+            char[] chars = str_origin.ToCharArray();
+            byte[] bytes = new byte[chars.Length];
+            for (int i = 0; i < chars.Length; i++)
+            {
+                int c = (int)chars[i];
+                bytes[i] = (byte)c;
+            }
+            Encoding Encoding_GB2312 = Encoding.GetEncoding("GB2312");
+            string str_converted = Encoding_GB2312.GetString(bytes);
+            return str_converted;
+        }
+    }
+}

+ 146 - 0
MyMemcached/TelnetCmd.Designer.cs

@@ -0,0 +1,146 @@
+namespace MyMemcached
+{
+    partial class TelnetCmd
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TelnetCmd));
+            this.cmdText = new System.Windows.Forms.TextBox();
+            this.btnGo = new System.Windows.Forms.Button();
+            this.cmdResult = new System.Windows.Forms.RichTextBox();
+            this.ServerList = new System.Windows.Forms.ComboBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.usefulCmd = new System.Windows.Forms.ComboBox();
+            this.SuspendLayout();
+            // 
+            // cmdText
+            // 
+            this.cmdText.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmdText.Location = new System.Drawing.Point(14, 69);
+            this.cmdText.Name = "cmdText";
+            this.cmdText.Size = new System.Drawing.Size(347, 21);
+            this.cmdText.TabIndex = 0;
+            this.cmdText.KeyDown += new System.Windows.Forms.KeyEventHandler(this.cmdText_KeyDown);
+            // 
+            // btnGo
+            // 
+            this.btnGo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnGo.Location = new System.Drawing.Point(367, 67);
+            this.btnGo.Name = "btnGo";
+            this.btnGo.Size = new System.Drawing.Size(75, 23);
+            this.btnGo.TabIndex = 1;
+            this.btnGo.Text = "执行";
+            this.btnGo.UseVisualStyleBackColor = true;
+            this.btnGo.Click += new System.EventHandler(this.btnGo_Click);
+            // 
+            // cmdResult
+            // 
+            this.cmdResult.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmdResult.EnableAutoDragDrop = true;
+            this.cmdResult.Location = new System.Drawing.Point(13, 96);
+            this.cmdResult.Name = "cmdResult";
+            this.cmdResult.ReadOnly = true;
+            this.cmdResult.Size = new System.Drawing.Size(429, 399);
+            this.cmdResult.TabIndex = 3;
+            this.cmdResult.Text = "";
+            // 
+            // ServerList
+            // 
+            this.ServerList.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.ServerList.FormattingEnabled = true;
+            this.ServerList.Location = new System.Drawing.Point(14, 13);
+            this.ServerList.Name = "ServerList";
+            this.ServerList.Size = new System.Drawing.Size(347, 20);
+            this.ServerList.TabIndex = 4;
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(365, 43);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(77, 12);
+            this.label1.TabIndex = 5;
+            this.label1.Text = "常用命令模板";
+            // 
+            // usefulCmd
+            // 
+            this.usefulCmd.FormattingEnabled = true;
+            this.usefulCmd.Items.AddRange(new object[] {
+            "stats",
+            "stats items",
+            "stats cachedump <slab_id> <limit_num>",
+            "set <key> <flags> <exptime> <bytes>",
+            "set <key> <value>",
+            "get <key>",
+            "gets <key>",
+            "cas <key> <flags> <exptime> <bytes> <gets.last>",
+            "cas <key> <gets.last> <value>",
+            "stats slabs",
+            "stats sizes",
+            "stats reset",
+            "flush_all"});
+            this.usefulCmd.Location = new System.Drawing.Point(14, 39);
+            this.usefulCmd.Name = "usefulCmd";
+            this.usefulCmd.Size = new System.Drawing.Size(347, 20);
+            this.usefulCmd.TabIndex = 6;
+            this.usefulCmd.SelectedIndexChanged += new System.EventHandler(this.usefulCmd_SelectedIndexChanged);
+            // 
+            // TelnetCmd
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(458, 507);
+            this.Controls.Add(this.usefulCmd);
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.ServerList);
+            this.Controls.Add(this.cmdResult);
+            this.Controls.Add(this.btnGo);
+            this.Controls.Add(this.cmdText);
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.Name = "TelnetCmd";
+            this.Text = "memcached命令操作";
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TextBox cmdText;
+        private System.Windows.Forms.Button btnGo;
+        private System.Windows.Forms.RichTextBox cmdResult;
+        private System.Windows.Forms.ComboBox ServerList;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.ComboBox usefulCmd;
+    }
+}

+ 140 - 0
MyMemcached/TelnetCmd.cs

@@ -0,0 +1,140 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+namespace MyMemcached
+{
+    public partial class TelnetCmd : Form
+    {
+        Stack<string> up = new Stack<string>();
+        Stack<string> down = new Stack<string>();
+        public TelnetCmd()
+        {
+            InitializeComponent();
+            ServerListBind();
+        }
+
+        private void btnGo_Click(object sender, EventArgs e)
+        {
+            cmdResult.AppendText(string.Format("-------{0}:{1}-------", ServerList.SelectedItem.ToString(), cmdText.Text));
+
+            string usefulcmd = usefulCmd.SelectedItem != null ? usefulCmd.SelectedItem.ToString() : string.Empty;
+            if (usefulcmd.EndsWith("<value>"))
+            {
+                try
+                {
+                    string[] cmd = cmdText.Text.Split();
+                    if (cmd[0] == "set")
+                    {
+                        string realcmd = string.Format("set {0} 0 30 {1}", cmd[1], cmd[2].Length);
+                        Run(realcmd);
+                        realcmd = cmd[2];
+                        Run(realcmd);
+                    }
+                    else if (cmd[0] == "cas")
+                    {
+                        string realcmd = string.Format("cas {0} 0 0 {1} {2}", cmd[1], cmd[3].Length, cmd[2]);
+                        Run(realcmd);
+                        realcmd = cmd[3];
+                        Run(realcmd);
+                    }
+                    else
+                    {
+                        Run(cmdText.Text);
+                    }
+                }
+                catch
+                {
+                    MessageBox.Show("命令格式错误");
+                }
+            }
+            else
+            {
+                Run(cmdText.Text);
+            }
+
+            int count = down.Count;
+            for (int i = 0; i < count; i++)
+            {
+                up.Push(down.Pop());
+            }
+            up.Push(cmdText.Text);
+            cmdText.Text = string.Empty;
+            cmdText.Focus();
+        }
+
+        private void Run(string cmd)
+        {
+            TelnetConnection telnet = Servers.ServerList[ServerList.SelectedItem.ToString()];
+            telnet.WriteLine(cmd);
+            cmdResult.AppendText(string.Format("\r\n{0}\r\n", telnet.Read()));
+            cmdResult.ScrollToCaret();
+        }
+
+        private void cmdText_KeyDown(object sender, KeyEventArgs e)
+        {
+            switch (e.KeyValue)
+            {
+                //回车
+                case 13:
+                    btnGo_Click(sender, e);
+                    break;
+                //up
+                case 38:
+                    StackWork(up, down);
+                    break;
+                //down
+                case 40:
+                    StackWork(down, up);
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// 上下按键取回textbox的输入记录
+        /// </summary>
+        /// <param name="beofre"></param>
+        /// <param name="after"></param>
+        private void StackWork(Stack<string> beofre, Stack<string> after)
+        {
+            string val;
+            if (beofre.Count <= 0)
+                return;
+            val = beofre.Pop();
+            cmdText.Text = val;
+            if (after.Count > 0)
+            {
+                if (!after.Peek().Equals(val))
+                { after.Push(val); }
+            }
+            else
+            {
+                after.Push(val);
+            }
+        }
+
+        //绑定combobox的数据
+        private void ServerListBind()
+        {
+            if (Servers.ServerList.Keys.Count == 0) return;
+
+            foreach (var server in Servers.ServerList.Keys)
+            {
+                ServerList.Items.Insert(0, server);
+            }
+            ServerList.SelectedIndex = 0;
+        }
+
+        private void usefulCmd_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            string cmd = usefulCmd.SelectedItem.ToString().Split(new char[] { '<' })[0];
+            cmdText.Text = cmd;
+            cmdText.Focus();
+            cmdText.SelectionStart = cmd.Length;
+        }
+    }
+}

Diff do ficheiro suprimidas por serem muito extensas
+ 6185 - 0
MyMemcached/TelnetCmd.resx


+ 86 - 0
MyMemcached/mcacheClientExt.cs

@@ -0,0 +1,86 @@
+using System;
+using System.Configuration;
+using Enyim.Caching.Configuration;
+using Enyim.Caching.Memcached;
+using System.Collections.Generic;
+using System.Threading;
+using System.Net;
+using System.Diagnostics;
+using Enyim.Caching;
+using Enyim.Caching.Memcached.Results;
+using Enyim.Caching.Memcached.Results.Factories;
+using Enyim.Caching.Memcached.Results.Extensions;
+using System.Text;
+using System.IO;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Text.RegularExpressions;
+
+namespace MyMemcached
+{
+    public class mcacheClientExt : MemcachedClient
+    {
+        public mcacheClientExt():base()
+        {
+        }
+        public mcacheClientExt(MemcachedClientConfiguration config)
+            : base(config)
+        {
+        }
+
+        protected override IGetOperationResult PerformTryGet(string key, out ulong cas, out object value)
+        {
+            var hashedKey = base.KeyTransformer.Transform(key);
+            var node = base.Pool.Locate(hashedKey);
+            var result = GetOperationResultFactory.Create();
+
+            cas = 0;
+            value = null;
+
+            if (node != null)
+            {
+                var command = base.Pool.OperationFactory.Get(hashedKey);
+                var commandResult = node.Execute(command);
+
+                if (commandResult.Success)
+                {
+                    try
+                    {
+                        result.Value = base.Transcoder.Deserialize(command.Result);
+                        value = null;
+                    }
+                    catch
+                    {
+                        result.Success = false;
+                        result.Value = "找不到该缓存所在的程序集.";
+
+                        //经调试发现,就算没有相应的DLL ,command.Result.Data.Array可以获取该值的类型
+                        value = "估计类型:" + Regex.Split(Encoding.UTF8.GetString(command.Result.Data.Array).Trim(), @"\0+")[7];
+                    }
+                   
+                    result.Cas = cas = command.CasValue;
+
+                    if (base.PerformanceMonitor != null)
+                        base.PerformanceMonitor.Get(1, true);
+
+                    //返回时 用IP地址替换result.Message(默认null)
+                    result.Pass(node.EndPoint.ToString());
+                    return result;
+                }
+                else
+                {
+                    commandResult.Combine(result);
+                    return result;
+                }
+            }
+
+            result.Value = value;
+            result.Cas = cas;
+
+            if (base.PerformanceMonitor != null)
+                base.PerformanceMonitor.Get(1, false);
+
+            result.Fail("Unable to locate node");
+            return result;
+        }
+    }
+}

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+参考
+----
+[Memcached windows 下安装与测试](http://www.cnblogs.com/wucg/archive/2011/03/01/1968185.html)

+ 12 - 0
memcached/INSTALL

@@ -0,0 +1,12 @@
+Installation instructions for Win32 memcached
+
+1. In a command shell, create a directory of your choice name and location
+2. Unzip the archive memcached-win32-1.4.4-14.zip in this location
+3. Run on the command line: memcached.exe -d install
+4. Run, from the Start button "Administrative Tools -> "Services"
+5. Double-click on the listing for "memcached"
+6. In the panel, you will see:
+  * "Startup type:" - this should be "automatic"
+  * "Service status:". Click the start button to start memcached (As shown in the image below)Windows_service
+
+7. Enjoy using memcached!

+ 3 - 0
memcached/README

@@ -0,0 +1,3 @@
+Thank you for downloading memcached for win32! Brought to you by Northscale Technologies.
+
+Please see the file INSTALL for installation instructions.

BIN
memcached/libgcc_s_sjlj-1.dll


BIN
memcached/memcached.exe


BIN
memcached/mingwm10.dll


BIN
memcached/pthreadGC2.dll


+ 1 - 0
version.txt

@@ -0,0 +1 @@
+version 3.6