• WPF界面手机QQ_DEMO


    参考别人研究的QQ协议做的简单的WPF版手机QQ聊天器,界面不太美观!

    简单功能:

    1.登陆
    2.消息查看器
    3.托盘消息闪烁
    4.查看个人基本资料
    5.聊天
    6.点击闪烁图标与最近的好友聊天

    截图


    主要通讯核心类:(有些是参考的网上的,基本上自己都改动过)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Security.Cryptography;
    using System.Text.RegularExpressions;
    using System.Threading;
    using My.Properties;
    
    namespace My
    {
    
        /// <summary>
        /// 获取腾讯QQ数据操作类
        /// </summary>
        public class ServerPostProcess
        {
            private string num = string.Empty;  //构造函数的QQ号码
            private string pwd = string.Empty; //构造函数的QQ密码
            private string md5Pwd = string.Empty;//加密后的QQ密码
    
            public string[] online_Face = { "" };       //在线的头像号码
            public string[] online_Station = { "" };    //在线的状态
            public string[] online_Number = { "" };     //在线的号码
            public string[] online_NameK = { "" };      //在线的昵称
    
            private WebClient wc1 = null;
            private WebClient wc2 = null;
            private WebClient wc3 = null;
    
            #region WebClient操作池(暂时放弃)出现_clientSends并发问题
            //private List<WebClient> _clientSends = new List<WebClient>(3); 
            //// <summary>
            //// 尝试从集合里面拿到一个发送器
            //// </summary>
            //private WebClient ClientSends
            //{
            //    get {
            //        lock (_clientSends)
            //        {
            //            int tnum = GetClientSendsNoBusyNum;
            //            if (_clientSends.Count <= 5 && tnum <= 0)
            //            {
            //                WebClient addWc = new WebClient();
            //                _clientSends.Add(addWc);
            //                return addWc;
            //            }
            //            if (tnum == 0)
            //            {
            //                return null;
            //            }
            //            //拿出一个不繁忙的发送器进行处理请求
            //            foreach (WebClient wct in _clientSends)
            //            {
            //                if (wct != null && !wct.IsBusy)
            //                {
            //                    return wct;
            //                }
            //            }
            //            return null;
            //        }
            //    }
            //}
            ///// <summary>
            ///// 获取发送器不繁忙的可用数量
            ///// </summary>
            //private int GetClientSendsNoBusyNum
            //{
            //    get
            //    {
            //        int i = 0;
            //        foreach (WebClient wc in _clientSends)
            //        {
            //            if (wc != null && !wc.IsBusy)
            //            {
            //                i++;
            //            }
            //        }
            //        return i;
            //    }
            //} 
            #endregion
    
            private string postStr;     //发送给服务器的字符串
            private byte[] postArray;   //把要发送的字符串变成字符数组
            private byte[] returnArray;  //接受服务器返回的字符数组
            private string returnStr;    //把返回的字符数组变成字符串
    
            public string[] MT;    //储存信息类型
            public string[] UN;    //储存信息来源号码
            public string[] MG;    //储存信息内容
    
            public bool is_RightLogin;//是否正确的登陆
    
            /// <summary>
            /// 登陆前提:必须通过验证
            /// </summary>
            public ServerPostProcess()
            {
                Users user = ManagerStaticResouce.LoginingUser;
                if (user != null)
                {
                    num = user.Uid;
                    pwd = user.Pwd;
                }
                else
                {
                    throw new Exception("用户名称不存在!");
                }
                wc1 = new WebClient();
                wc2 = new WebClient();
                wc3 = new WebClient();
                md5Pwd = MD5(pwd);
            }
    
            /// <summary>
            /// 向服务器POST数据
            /// </summary>
            private bool UploadData(int type)
            {
                try
                {
                    WebClient wc = GetClientSends(type);//尝试拿到一个发送器
                    if (wc != null)//双重判断
                    {
                        returnArray = wc.UploadData("http://tqq.tencent.com:8000", "POST", postArray);
                    }
                    else
                    {
                        return false;
                    }
                }
                catch (Exception ex)
                {
                    throw new WebException(ex.Message);
                }
                return true;
            }
    
            /// <summary>
            /// 得到一个发送器
            /// </summary>
            /// <param name="type">操作类型(1 其他,2 发送消息,3 获取消息)</param>
            /// <returns></returns>
            private WebClient GetClientSends(int type)
            {
                if (wc1 != null && !wc1.IsBusy && type == 1)
                {
                    return wc1;
                }
                else if (wc2 != null && !wc2.IsBusy && type == 2)
                {
                    return wc2;
                }
                else if (wc3 != null && !wc3.IsBusy && type==3)
                {
                    return wc3;
                }
                else
                {
                    return null;
                }
            }
    
            /// <summary>
            /// 登陆QQ
            /// </summary>
            /// <returns>登陆成功就返回True</returns>
            public bool QQ_Login(ref string returnResult)
            {
                postStr = "VER=1.1&CMD=Login&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7)
                    + "&UIN=" + num + "&PS=" + md5Pwd + " &M5=1&LC=9326B87B234E7235";
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
    
                if (!UploadData(1))
                {
                    returnResult = "服务器忙!请重新点击登陆!";
                    return false;
                }
    
                returnStr = Encoding.UTF8.GetString(returnArray);
                returnResult = returnStr;
                if (returnStr.Contains("RES=0&RS=0"))
                {
                    is_RightLogin = true;
                    return true;
                }
                else
                {
                    return false;
                }
            }
    
            /// <summary>
            /// QQ退出登陆,并改变is_RightLogin为False
            /// </summary>
            public void QQ_Logout()
            {
                postStr = "VER=1.1&CMD=Logout&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num;
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                while (true)
                {
                    if (!UploadData(1))
                    {
                        continue;
                    }
                    break;
                }
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (returnStr.Contains("&RES=0"))
                {
                    is_RightLogin = false;
                    return;
                }
            }
    
            /// <summary>
            /// MD5加密
            /// </summary>
            /// <param name="toCryString"></param>
            /// <returns></returns>
            public static string MD5(string toCryString)
            {
                //using System.Security.Cryptography安全.密码系统
                MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                //asp是小写,把所有字符变小写
                string tmp =BitConverter.ToString(hashmd5.ComputeHash(Encoding.UTF8.GetBytes(toCryString))).Replace("-", "").ToLower();
                hashmd5.Clear();
                return tmp;
            }
    
            /// <summary>
            /// 获取QQ好友列表
            /// </summary>
            /// <returns>返回一个字符串数组,数组最后一个元素是空格</returns>
            public string[] QQ_List()
            {
                postStr = "VER=1.1&CMD=List&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&TN=160&UN=0";
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                if (!UploadData(1))
                {
                    return null;
                }
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (!returnStr.Contains("&RES=0"))
                    is_RightLogin = false;
                string s2 = returnStr.Remove(0, returnStr.IndexOf("&UN=") + 4);
                string[] QQ_Friend_List = s2.Split(',');
                return QQ_Friend_List;
            }
    
            /// <summary>
            /// 更新QQ类中目前在线online_四个字符串数组的值
            /// </summary>
            public void QQ_Query_Stat()
            {
                postStr = "VER=1.1&CMD=Query_Stat&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&TN=50&UN=0";
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                if (!UploadData(1))
                {
                    return;
                }
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (!returnStr.Contains("&RES=0"))
                    is_RightLogin = false;
                StringBuilder sb = new StringBuilder(returnStr);
                sb.Remove(returnStr.IndexOf("&FN="), returnStr.Length - returnStr.IndexOf("&FN="));
                sb.Remove(0, returnStr.IndexOf("&FC=") + 4);
                online_Face = sb.ToString().Split(',');
    
                sb = new StringBuilder(returnStr);
                sb.Remove(returnStr.IndexOf("&UN="), returnStr.Length - returnStr.IndexOf("&UN="));
                sb.Remove(0, returnStr.IndexOf("&ST=") + 4);
                online_Station = sb.ToString().Split(',');
    
                sb = new StringBuilder(returnStr);
                sb.Remove(returnStr.IndexOf("&NK="), returnStr.Length - returnStr.IndexOf("&NK="));
                sb.Remove(0, returnStr.IndexOf("&UN=") + 4);
                online_Number = sb.ToString().Split(',');
    
                string ss = returnStr.Remove(0, returnStr.IndexOf("&NK=") + 4);
                online_NameK = ss.Split(',');
            }
    
            /// <summary>
            /// 输入一个QQ号,查询这个QQ号的信息
            /// </summary>
            /// <param name="search_num">输入一个QQ号,查询该QQ信息</param>
            /// <returns>字符串数组(0联系地址,1用户年龄,2用户邮箱,3头像,4个人网站,5职业,6邮箱,7联系电话,8简介,9省份,10真实姓名,11毕业院校,12性别,13QQ号,14昵称)</returns>
            public string[] QQ_GetInfo(string search_num)
            {
                postStr = "VER=1.1&CMD=GetInfo&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&LV=2&UN=" + search_num;
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                if (!UploadData(1))
                {
                    return null;
                }
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (!returnStr.Contains("&RES=0"))
                    is_RightLogin = false;
                MatchCollection matches = Regex.Matches(returnStr, "&([^=][^=])=([^&]*)");
                List<string> Info = new List<string>();
                for (int i = 0; i < matches.Count; i++)
                    Info.Add(matches[i].Groups[2].ToString());
                Info.RemoveAt(6);   //去除LV=多少, 这表示查询方式,默然就是普通查询
                if (Info[12].ToString() == "0")
                    Info[12] = "男";
                else
                    Info[12] = "女";
                string[] Inf = Info.ToArray();
                return Inf;
            }
    
            /// <summary>
            /// 添加好友功能
            /// </summary>
            /// <param name="fir_num">输入一个QQ号,请求加为好友</param>
            /// <returns>0表示已经加为好友,1表示需要验证请求,2表示拒绝</returns>
            public string AddToList(string fir_num)
            {
                postStr = "VER=1.1&CMD=AddToList&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + fir_num;
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                if (!UploadData(1))
                {
                    return null;
                }
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (!returnStr.Contains("&RES=0"))
                    is_RightLogin = false;
                MatchCollection matchs = Regex.Matches(returnStr, "&CD=(.)");
                return matchs[0].Groups[1].ToString();
            }
    
            /// <summary>
            /// 回应加为好友的响应
            /// </summary>
            /// <param name="fri_Num">请求的QQ号码</param>
            /// <param name="agree_Type">0表示通过验证,1表示拒绝对方,2表示请求加对方为好友</param>
            public void Ack_AddToList(string fri_Num, string agree_Type)
            {
                postStr = "VER=1.1&CMD=Ack_AddToList&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + fri_Num + "&CD=" + agree_Type + "&RS=";
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                if (!UploadData(1))
                {
                    return;
                }
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (!returnStr.Contains("&RES=0"))
                    is_RightLogin = false;
            }
    
            /// <summary>
            /// 删除好友,成功返回True
            /// </summary>
            /// <param name="del_num">输入一个QQ号,删除这个QQ好友</param>
            /// <returns></returns>
            public bool DelFromList(string del_num)
            {
                postStr = "VER=1.1&CMD=DelFromList&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + del_num;
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                if (!UploadData(1))
                {
                    return false;
                }
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (returnStr.Contains("&RES=0"))
                    return true;
                else
                    return false;
            }
    
            /// <summary>
            /// 改变QQ当前状态(在线,离线,忙碌)
            /// </summary>
            /// <param name="Stat">输入10在线,20离线,30忙碌</param>
            /// <returns></returns>
            public bool Change_Stat(string stat)
            {
                postStr = "VER=1.1&CMD=Change_Stat&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&ST=" + stat;
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                if (!UploadData(1))
                {
                    return false;
                }
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (returnStr.Contains("&RES=0"))
                    return true;
                else
                    return false;
            }
    
            /// <summary>
            /// 向一个QQ号码发送消息
            /// </summary>
            /// <param name="msgTo">输入一个QQ号,向他发送消息</param>
            /// <param name="msg">输入消息内容</param>
            /// <returns>成功返回True</returns>
            public bool QQ_SendMsg(string msgTo, string msg)
            {
                postStr = "VER=1.2&CMD=CLTMSG&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + msgTo + "&MG=" + msg;
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                if (!UploadData(2))
                {
                    return false;
                }
    
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (returnStr.Contains("&RES=20"))
                {
                    is_RightLogin = false;
                    return false;
                }
                if (returnStr.Contains("&RES=0"))
                    return true;
                else
                    return false;
            }
    
            //待处理
            public void GetMsgEx()
            {
                postStr = "VER=1.1&CMD=GetMsgEx&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num;
                postArray = System.Text.Encoding.UTF8.GetBytes(postStr);
                //向服务器POST数据
                if (!UploadData(3))
                {
                    return;
                }
                returnStr = Encoding.UTF8.GetString(returnArray);
                if (returnStr.Contains("\r"))
                    returnStr = returnStr.Replace("\r", "\n");
                if (returnStr.Contains("&RES=0") && returnStr.Contains("&MN="))
                {
                    is_RightLogin = true;
                    MatchCollection matches = Regex.Matches(returnStr, "&MN=([^&]*)");
    
                    if (matches[0].Groups[1].ToString() != "0") //判断返回的信息数量是否为0条
                    {
                        matches = Regex.Matches(returnStr, "&MT=([^&]*)&UN=([^&]*)&MG=([^&]*)");
                        MT = matches[0].Groups[1].ToString().Split(',');   //信息类型
                        UN = matches[0].Groups[2].ToString().Split(',');   //信息来源号码
                        returnStr = returnStr.Remove(0, returnStr.IndexOf("&MG=") + 4);
                        MG = returnStr.Split(',');   //信息内容
                        //将消息内容进行转码
                        for (int i = 0; i < MG.Length - 1; i++)
                        {
                            MG[i] = MG[i].Replace("%25", "%");
                            MG[i] = MG[i].Replace("%26", "&");
                            MG[i] = MG[i].Replace("%2c", ",");
                        }
                    }
                    else
                    {
                        MT = null;
                        UN = null;
                        MG = null;
                        is_RightLogin = false;
                    }
                }
                else
                {
                    MT = null;
                    UN = null;
                    MG = null;
                    is_RightLogin = false;
                }
            }
    
            
    
    
        }
    }
    

    此程序纯属好玩,单纯的只想研究下手机QQ的协议.
    注意没有使用过手机登陆过QQ的用户可能无法正常登陆,解决办法是使用真正的手机QQ登陆一次即可.
    程序下载:NatureQQ
    源码下载:NatureQQ_Source

  • 相关阅读:
    ManualResetEvent详解
    MEF搜索范围
    ThreadStart和ParameterizedThreadStart区别
    快速理解C#高级概念(一) Delegate委托
    c# 多线程 --Mutex(互斥锁)
    sql server 得到数据库字典
    遇到的坑:在线用户统计的实现
    asp.net core 使用EF7 Code First 创建数据库,同时使用命令创建数据库
    使用cachemanager做缓存(Session的缓存)
    C# web api返回类型设置为json的两种方法
  • 原文地址:https://www.cnblogs.com/NatureSex/p/2167437.html
Copyright © 2020-2023  润新知