예제 #1
0
        private bool DoPcMobileLogin(string UserID, string DataTerminalName, string DataGroup, string DataText, SocketUserToken userToken, SocketUserTokenList UserTokenList)
        {
            bool Passed = true, Done = false;
            SocketUserToken ExistsUser = UserTokenList[UserID];
            if (ExistsUser != null)
            {
                Socket curSkt = ExistsUser.ConnectSocket;
                string curIPAddress = ExistsUser.ConnectSocket.RemoteEndPoint.ToString();
                #region " 發送離線 "

                try
                {
                    List<byte[]> msgs = ParseProtocol.ConvertMsgToByte("00", "7", UserID, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper(), "");
                    //如果2秒內得不到之前登陸的對象,就直接干掉
                    //否則此帳號將永遠無法登錄
                    if (Monitor.TryEnter(curSkt, 2000))
                    {
                        try
                        {
                            //向用戶本人發送離線
                            foreach (byte[] msg in msgs)
                            {
                                //2016/05/19 test
                                ExistsUser.AsyncSendAgent.DoSendBuffer(msg);
                                //curSkt.Send(msg);
                                //SendData(curSkt, msg);
                            }
                        }
                        catch (SocketException ex)
                        {
                            LogHelper.WriteLog("DoPcMobileLogin()", "執行向" + DataGroup + "用戶: " + UserID + " [" + curIPAddress + "] 發送強制離線[不允許自動重連]消息時:" + (ex != null ? ex.Message : ""));
                        }
                        finally
                        {
                            Monitor.Exit(curSkt);
                        }
                    }
                    else
                    {
                        //如果到這里說明之前登陸的對象已經死鎖  
                        LogHelper.WriteLog("DoPcMobileLogin()", "嘗試使用Monitor.TryEnter鎖定" + DataGroup + "用戶: " + UserID + " [" + curIPAddress + "] 時失敗.");
                    }
                }
                catch (SocketException ex)
                {
                    LogHelper.WriteLog("DoPcMobileLogin()", "向" + DataGroup + "用戶: " + UserID + " [" + curIPAddress + "] 發送離線[不允許自動重連]消息時:" + (ex != null ? ex.Message : ""));
                }

                try
                {
                    //運行到這里時,有可能客戶端收到7-00之後主動斷開連接,則會觸發CloseClientSocket.
                    if (!ExistsUser.Closing)
                    {
                        //ExistsUser.Closing = true;
                        CloseClientSocket(ExistsUser);
                    }

                    LogHelper.WriteLog("DoPcMobileLogin", string.Format("因相同帳號再次登錄,強制先登錄的用戶{0} [{1}] 下線.", UserID, curIPAddress));

                    UpdateUserLog(UserID, "1", "0", "因相同帳號再次登陸而強制離線.", "", null);
                }
                catch (SocketException ex)
                {
                    LogHelper.WriteLog("DoPcMobileLogin()", "嘗試關閉" + DataGroup + "用戶: " + UserID + " [" + curIPAddress + "] 線程和Socket連接時出錯." + (ex != null ? ex.Message : ""));
                }

                #endregion
            }
            // 驗證是否為唯一用戶
            if (UserTokenList.ContainsKey(UserID))
            {
                //到這里說明前面強制離線沒有成功
                try
                {
                    List<byte[]> msgs = ParseProtocol.ConvertMsgToByte("登錄失敗.", "3", UserID, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper(), "");
                    //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                    lock (userToken.ConnectSocket)
                    {
                        foreach (byte[] msg in msgs)
                        {
                            //同步發送
                            //2016/05/19 test
                            userToken.AsyncSendAgent.DoSendBuffer(msg);
                            //userToken.ConnectSocket.Send(msg);
                            //SendData(userToken.ConnectSocket, msg);
                        }
                    }
                    LogHelper.WriteLog("ProcessLogin()", DataGroup + "用戶:" + UserID + "登錄失敗");
                }
                catch (SocketException ex)
                {
                    LogHelper.WriteLog("ProcessLogin()", "發送登陸失敗信息時" + (ex != null ? ex.Message : ""));
                }
            }
            else
            {
                // 服務器開放登錄功能
                try
                {
                    List<byte[]> msgs = ParseProtocol.ConvertMsgToByte("登錄成功.", "2", UserID, DataTerminalName, DataGroup, Guid.NewGuid().ToString().Replace("-", "").ToUpper(), "");
                    //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                    lock (userToken.ConnectSocket)
                    {
                        foreach (byte[] msg in msgs)
                        {
                            //2016/05/19 test
                            userToken.AsyncSendAgent.DoSendBuffer(msg);
                            //userToken.ConnectSocket.Send(msg);
                            //SendData(userToken.ConnectSocket, msg);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Passed = false;
                    LogHelper.WriteLog("ProcessLogin()", "發送登錄成功信息時" + (ex != null ? ex.Message : ""));
                }

                if (Passed)
                {
                    //設置對象狀態
                    userToken.BindingUser = new User();
                    userToken.BindingUser.State = User.UserStates.Online;
                    userToken.BindingUser.Role = (DataGroup.Length > 0 ? User.UserRole.Mobile : User.UserRole.PC);
                    //移動設備登錄為: 
                    //iPhone = "IPHONE"
                    //iPad = "IPAD"
                    //Android Phone = "APHONE"
                    //Android Pad = "APAD"
                    switch (DataGroup.ToUpper())
                    {
                        case "IPHONE":
                            userToken.BindingUser.Mobile = User.UserMobileType.iPhone;
                            //iToken
                            userToken.BindingUser.iToken = DataText;
                            break;
                        case "IPAD":
                            userToken.BindingUser.Mobile = User.UserMobileType.iPad;
                            //iToken
                            userToken.BindingUser.iToken = DataText;
                            break;
                        case "APHONE":
                            userToken.BindingUser.Mobile = User.UserMobileType.AndroidPhone;
                            break;
                        case "APAD":
                            userToken.BindingUser.Mobile = User.UserMobileType.AndroidPad;
                            break;
                        default:
                            //默認PC
                            userToken.BindingUser.Mobile = User.UserMobileType.None;
                            break;
                    }
                    userToken.BindingUser.ID = UserID;
                    //Mac
                    userToken.BindingUser.MacAddr = DataTerminalName;
                    //IP
                    userToken.BindingUser.IP = ((IPEndPoint)userToken.ConnectSocket.RemoteEndPoint).Address.ToString();
                    //設備名稱
                    userToken.BindingUser.DevName = DataText;
                    Socket newClient = userToken.ConnectSocket;

                    string UserRegion = "";

                    using (SQLHelper conn = new SQLHelper(DBInfo))
                    {
                        conn.OpenConnection();
                        try
                        {
                            //取消日誌
                            //LogHelper.WriteLog("ProcessLogin()", "#5.登錄成功,準備截入聯絡人信息及推送未讀消息. " + UserID + " [" + userToken.ConnectSocket.RemoteEndPoint + "]");

                            #region " 載入聯絡人清單(聯絡人變更時應更新) "

                            DataTable ContactsList = GetContacts(conn, UserID);
                            if (ContactsList.Rows.Count > 0)
                            {
                                foreach (DataRow Contact in ContactsList.Rows)
                                {
                                    //加入聯絡人(防呆自己加自己)
                                    if (UserID != Contact["contact_id"].ToString())
                                        userToken.BindingUser.Contacts.Add(Contact["contact_id"].ToString());
                                }
                            }
                            ContactsList = null;

                            #endregion

                            #region " 當PC端和Mobile端未登錄的情況下才向其聯絡人推送用戶上線消息 "

                            if (!m_pcUserTokenList.ContainsKey(UserID) && !m_mobileUserTokenList.ContainsKey(UserID))
                                //ID,狀態,簽名,聯絡人清單,頭像數據
                                if (userToken.BindingUser.Contacts.Count > 0)
                                    StateNotifyQueue.Enqueue(new List<object>() { userToken.BindingUser.ID, "1", userToken.BindingUser.Signature, userToken.BindingUser.Contacts, null });

                            #endregion

                            #region " 發送所有未讀訊息和群命令 "

                            #region " 訊息 "

                            DataTable MsgsList = GetUnreadMsgs(conn, UserID, "M");
                            if (MsgsList.Rows.Count > 0)
                            {
                                if (newClient != null)
                                {
                                    if (MsgsList.Rows.Count > 0)
                                    {
                                        long MaxMsgNO = 0;
                                        foreach (DataRow UnreadMsg in MsgsList.Rows)
                                        {
                                            // 記錄最大MsgNO
                                            if (MaxMsgNO < long.Parse(UnreadMsg["msg_no"].ToString()))
                                                MaxMsgNO = long.Parse(UnreadMsg["msg_no"].ToString());

                                            // 發給登錄人
                                            DateTime MsgDT = DateTime.Parse(UnreadMsg["msg_date"].ToString() + " " + UnreadMsg["msg_time"].ToString());
                                            // 判斷個人消息還是群消息
                                            // 消息子類型(msg_doctype)(文字消息/文件消息) 
                                            // 0 = File 
                                            // 1 = Text Msg 
                                            // 2 = offline File
                                            // 3 = 截圖
                                            // 4 = email 
                                            // 5 = 抖動
                                            // 6 = 音頻
                                            List<byte[]> rtnMsgs = null;
                                            switch (UnreadMsg["msg_doctype"].ToString())
                                            {
                                                case "0":
                                                    rtnMsgs = ParseProtocol.ConvertMsgToByte(UnreadMsg["msg_text"].ToString(),
                                                                "P",
                                                                UnreadMsg["msg_from"].ToString(),
                                                                UnreadMsg["user_name"].ToString(),
                                                                "S",
                                                                MsgDT,
                                                                UnreadMsg["msg_guid"].ToString(),
                                                                UnreadMsg["msg_no"].ToString(),
                                                                      "");
                                                    break;
                                                case "2":
                                                    rtnMsgs = ParseProtocol.ConvertMsgToByte(UnreadMsg["msg_text"].ToString(),
                                                                "P",
                                                                UnreadMsg["msg_from"].ToString(),
                                                                UnreadMsg["user_name"].ToString(),
                                                                "O",
                                                                MsgDT,
                                                                UnreadMsg["msg_guid"].ToString(),
                                                                UnreadMsg["msg_no"].ToString(),
                                                                      "");
                                                    break;
                                                case "3":
                                                    rtnMsgs = ParseProtocol.ConvertMsgToByte((byte[])UnreadMsg["msg_img"],
                                                                "I",
                                                                UnreadMsg["msg_from"].ToString(),
                                                                UnreadMsg["user_name"].ToString(),
                                                                UnreadMsg["td_no"].ToString(),
                                                                MsgDT,
                                                                UnreadMsg["msg_guid"].ToString(),
                                                                UnreadMsg["msg_no"].ToString(),
                                                                      "");
                                                    break;
                                                case "4":
                                                    rtnMsgs = ParseProtocol.ConvertMsgToByte(UnreadMsg["msg_text"].ToString(),
                                                                "M",
                                                                UnreadMsg["msg_from"].ToString(),
                                                                UnreadMsg["user_name"].ToString(),
                                                                UnreadMsg["td_no"].ToString(),
                                                                MsgDT,
                                                                UnreadMsg["msg_guid"].ToString(),
                                                                UnreadMsg["msg_no"].ToString(),
                                                                      "");
                                                    break;
                                                case "5":
                                                    rtnMsgs = ParseProtocol.ConvertMsgToByte(UnreadMsg["msg_text"].ToString(),
                                                                "Q",
                                                                UnreadMsg["msg_from"].ToString(),
                                                                UnreadMsg["user_name"].ToString(),
                                                                UnreadMsg["td_no"].ToString(),
                                                                MsgDT,
                                                                UnreadMsg["msg_guid"].ToString(),
                                                                UnreadMsg["msg_no"].ToString(),
                                                                      "");
                                                    break;
                                                case "6":
                                                    rtnMsgs = ParseProtocol.ConvertMsgToByte("Voice",
                                                                "R",
                                                                UnreadMsg["msg_from"].ToString(),
                                                                UnreadMsg["user_name"].ToString(),
                                                                UnreadMsg["td_no"].ToString(),
                                                                MsgDT,
                                                                UnreadMsg["msg_guid"].ToString(),
                                                                UnreadMsg["msg_no"].ToString(),
                                                                      "");
                                                    break;
                                                default:
                                                    //1
                                                    string DataType = "";
                                                    if (UnreadMsg["msg_type"].ToString() == "0")
                                                    {
                                                        //小助手系統消息
                                                        DataType = "5";
                                                    }
                                                    else
                                                    {
                                                        DataType = UnreadMsg["td_no"].ToString().Length > 0 ? "4" : (UnreadMsg["msg_doctype"].ToString() == "0" ? "P" : "U");
                                                    }
                                                    rtnMsgs = ParseProtocol.ConvertMsgToByte(UnreadMsg["msg_text"].ToString(),
                                                                DataType,
                                                                UnreadMsg["msg_from"].ToString(),
                                                                UnreadMsg["user_name"].ToString(),
                                                                UnreadMsg["td_no"].ToString(),
                                                                MsgDT,
                                                                UnreadMsg["msg_guid"].ToString(),
                                                                UnreadMsg["msg_no"].ToString(),
                                                                        "");
                                                    break;
                                            }
                                            //if (UnreadMsg["msg_doctype"].ToString() == "3")
                                            //{
                                            //    rtnMsgs = ParseProtocol.ConvertMsgToByte((byte[])UnreadMsg["msg_img"],
                                            //                                            "I",
                                            //                                            UnreadMsg["msg_from"].ToString(),
                                            //                                            UnreadMsg["user_name"].ToString(),
                                            //                                            UnreadMsg["td_no"].ToString(),
                                            //                                            MsgDT,
                                            //                                            UnreadMsg["msg_guid"].ToString(),
                                            //                                            UnreadMsg["msg_no"].ToString(),
                                            //                                                  "");
                                            //}
                                            //else
                                            //{
                                            //    rtnMsgs = ParseProtocol.ConvertMsgToByte(UnreadMsg["msg_text"].ToString(),
                                            //        UnreadMsg["td_no"].ToString().Length > 0 ? "4" : (UnreadMsg["msg_doctype"].ToString() == "0" ? "P" : "U"),
                                            //                                                    UnreadMsg["msg_from"].ToString(),
                                            //                                                    UnreadMsg["user_name"].ToString(),
                                            //                                                    UnreadMsg["td_no"].ToString(),
                                            //                                                    MsgDT,
                                            //                                                    UnreadMsg["msg_guid"].ToString(),
                                            //                                                    UnreadMsg["msg_no"].ToString(),
                                            //                                                          "");
                                            //}
                                            //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                                            lock (newClient)
                                            {
                                                foreach (byte[] msg in rtnMsgs)
                                                {
                                                    //2016/05/19 test
                                                    userToken.AsyncSendAgent.DoSendBuffer(msg);
                                                    //newClient.Send(msg);
                                                    //SendData(newClient, msg);
                                                }
                                            }
                                        }

                                        // 更新為已讀 
                                        try
                                        {
                                            MarkReadHistoryMsgQueue.Enqueue("update a set a.msg_state='1' from lrmsgstate a where a.msg_no<=" + MaxMsgNO.ToString() + " and a.msg_to='" + UserID + "' and a.msg_state='0'");
                                        }
                                        catch (Exception ex)
                                        {
                                            LogHelper.WriteLog("ProcessLogin()", "標識歷史信息為已讀時:" + (ex != null ? ex.Message : ""));
                                        }
                                    }
                                }
                                //Test
                                LogHelper.WriteLog("ProcessLogin()", "共向" + DataGroup + "用戶:" + userToken.BindingUser.ID + "推送" + MsgsList.Rows.Count.ToString() + "條歷史未讀消息.");
                            }

                            #endregion

                            #region " 系統消息 "

                            MsgsList = GetUnreadMsgs(conn, UserID, "S");
                            if (MsgsList.Rows.Count > 0)
                            {
                                if (newClient != null)
                                {
                                    if (MsgsList.Rows.Count > 0)
                                    {
                                        long MaxMsgNO = 0;
                                        foreach (DataRow UnreadMsg in MsgsList.Rows)
                                        {
                                            // 記錄最大MsgNO
                                            if (MaxMsgNO < long.Parse(UnreadMsg["sys_id"].ToString()))
                                                MaxMsgNO = long.Parse(UnreadMsg["sys_id"].ToString());

                                            // 發給登錄人
                                            DateTime MsgDT = DateTime.Parse(UnreadMsg["sys_date"].ToString() + " " + UnreadMsg["sys_time"].ToString());
                                            // 判斷個人消息還是群消息
                                            List<byte[]> rtnMsgs = ParseProtocol.ConvertMsgToByte(UnreadMsg["sys_remk"].ToString(),
                                                                                                  UnreadMsg["sys_type"].ToString() == "1" ? "D" : "*",
                                                                                                  UnreadMsg["sys_type"].ToString(),
                                                                                                  UnreadMsg["sys_objtype"].ToString(),
                                                                                                  "*",
                                                                                                  MsgDT,
                                                                                                  UnreadMsg["sys_objid"].ToString(),
                                                                                                  UnreadMsg["sys_id"].ToString(),
                                                                                                  "");
                                            //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                                            lock (newClient)
                                            {
                                                foreach (byte[] msg in rtnMsgs)
                                                {
                                                    //2016/05/19 test
                                                    userToken.AsyncSendAgent.DoSendBuffer(msg);
                                                    //newClient.Send(msg);
                                                    //SendData(newClient, msg);
                                                }
                                            }
                                        }

                                        // 更新為已讀 
                                        try
                                        {
                                            MarkReadHistoryMsgQueue.Enqueue("update a set a.sysmsg_state='1' from lrsysmsgstate a where a.sys_id<=" + MaxMsgNO.ToString() + " and a.sysmsg_to='" + UserID + "' and a.sysmsg_state='0'");
                                            //conn.ExecuteSQL("update a set a.msg_state='1' from lrmsgstate a where a.msg_no<=" + MaxMsgNO.ToString() + " and a.msg_to='" + UserID + "' and a.msg_state='0'");
                                        }
                                        catch (Exception ex)
                                        {
                                            LogHelper.WriteLog("ProcessLogin()", "標識歷史系統消息為已讀時:" + (ex != null ? ex.Message : ""));
                                        }
                                    }
                                }
                                //Test
                                //LogHelper.WriteLog("ProcessLogin()", "共向用戶:" + User.ID + "推送" + MsgsList.Rows.Count.ToString() + "條歷史命令.");
                            }

                            #endregion

                            MsgsList.Dispose();
                            MsgsList = null;

                            #endregion

                            //得到用戶區域代號
                            try
                            {
                                UserRegion = conn.OpenDataTable("select user_region from lrtduser (nolock) where user_no='" + UserID + "'", CommandType.Text).Rows[0][0].ToString();
                            }
                            catch
                            {
                                UserRegion = "";
                            }
                        }
                        catch (SocketException ex)
                        {
                            //test
                            //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "向PC端" + DataTerminal + "推送未讀信息時出錯." + (ex != null ? ex.Message : ""));
                            LogHelper.WriteLog("ProcessLogin()", "向" + DataGroup + "用戶:" + UserID + "推送未讀信息和系統消息時出錯." + (ex != null ? ex.Message : ""));
                        }

                        //更新用戶狀態
                        try
                        {
                            DoUpdateUserLog(conn, UserID, "0", ((int)userToken.BindingUser.Mobile).ToString(), DataGroup + "登錄", ((IPEndPoint)userToken.ConnectSocket.RemoteEndPoint).Address.ToString(), DataText, DataTerminalName, null);
                            DoUpdateUserState(conn, UserID, "1"); //上線中
                        }
                        catch (Exception ex)
                        {
                            Passed = false;
                            LogHelper.WriteLog("ProcessLogin()", "更新" + DataGroup + "用戶:" + UserID + "狀態." + (ex != null ? ex.Message : ""));
                        }

                        conn.CloseConnection();
                    }

                    //只推PC端用戶
                    if (Passed && DataGroup.Length == 0)
                    {
                        #region " 向PC客戶端推送平臺數據(在線人數等) "
                        try
                        {
                            List<byte[]> MsgToPC = ParseProtocol.ConvertMsgToByte(string.Format(SysMessage, ActiveUsersCount,
                                                                                                            OnlineUsersCount,
                                                                                                            RegisteredUsersCount,
                                                                                                            TodayMessagesCount,
                                                                                                            TotalMessagesCount),
                                                                                  "9", "", "", "", "", "");
                            //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                            lock (newClient)
                            {
                                foreach (byte[] msg in MsgToPC)
                                {
                                    //2016/05/19 test
                                    userToken.AsyncSendAgent.DoSendBuffer(msg);
                                    //newClient.Send(msg);
                                    //SendData(newClient, msg);
                                }
                            }
                        }
                        catch (SocketException ex)
                        {
                            //這個沒必要斷開
                            //Passed = false;
                            //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "向PC端" + DataTerminal + "推送未讀信息時出錯." + (ex != null ? ex.Message : ""));
                            LogHelper.WriteLog("ProcessLogin()", "向PC端" + UserID + "推送平臺數據(在線人數等)." + (ex != null ? ex.Message : ""));
                        }
                        #endregion

                        #region " 向PC客戶端推送系統公告 "
                        try
                        {
                            if (SysNotices.Count > 0 && UserRegion.Length > 0 && (SysNotices.ContainsKey(UserRegion) || SysNotices.ContainsKey("ALL")))
                            {
                                List<NoticeMsg> nMsgs;
                                // 全服廣播
                                object AllNotices = SysNotices["ALL"];
                                if (AllNotices != null)
                                {
                                    nMsgs = (List<NoticeMsg>)AllNotices;
                                    List<byte[]> MsgNotice;
                                    foreach (NoticeMsg nMsg in nMsgs)
                                    {
                                        MsgNotice = ParseProtocol.ConvertMsgToByte(nMsg.MsgText, "B", "1", nMsg.MsgSeq, "ALL", "", "");
                                        //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                                        lock (newClient)
                                        {
                                            foreach (byte[] msg in MsgNotice)
                                            {
                                                //2016/05/19 test
                                                userToken.AsyncSendAgent.DoSendBuffer(msg);
                                                //newClient.Send(msg);
                                                //SendData(newClient, msg);
                                            }
                                        }
                                    }
                                }
                                // 區域廣播
                                object RegionNotices = SysNotices[UserRegion];
                                if (RegionNotices != null)
                                {
                                    nMsgs = (List<NoticeMsg>)RegionNotices;
                                    List<byte[]> MsgNotice;
                                    foreach (NoticeMsg nMsg in nMsgs)
                                    {
                                        MsgNotice = ParseProtocol.ConvertMsgToByte(nMsg.MsgText, "B", "1", nMsg.MsgSeq, UserRegion, "", "");
                                        //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                                        lock (newClient)
                                        {
                                            foreach (byte[] msg in MsgNotice)
                                            {
                                                //2016/05/19 test
                                                userToken.AsyncSendAgent.DoSendBuffer(msg);
                                                //newClient.Send(msg);
                                                //SendData(newClient, msg);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        catch (SocketException ex)
                        {
                            //這個沒必要斷開
                            //Passed = false;
                            //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "向PC端" + DataTerminal + "推送未讀信息時出錯." + (ex != null ? ex.Message : ""));
                            LogHelper.WriteLog("ProcessLogin()", "向PC端" + UserID + "推送系統公告." + (ex != null ? ex.Message : ""));
                        }
                        #endregion
                    }

                    if (Passed)
                    {
                        //添加到正在執行的列表中
                        if (UserTokenList.ContainsKey(UserID))
                        {
                            ExistsUser = UserTokenList[UserID];
                            if (ExistsUser != null)
                            {
                                try
                                {
                                    LogHelper.WriteLog("DoPcMobileLogin", string.Format("加入在線人員列表時發現已有同名帳號在里面,強制用戶{0} [{1}] 下線.", UserID, ExistsUser.ConnectSocket.RemoteEndPoint));

                                    if (!ExistsUser.Closing)
                                    {
                                        //ExistsUser.Closing = true;
                                        CloseClientSocket(ExistsUser);
                                    }
                                }
                                catch (SocketException ex)
                                {
                                    LogHelper.WriteLog("ProcessLogin()", "嘗試關閉" + DataGroup + "用戶" + UserID + "線程和Socket連接時出錯." + (ex != null ? ex.Message : ""));
                                }
                            }
                            //LogHelper.WriteLog("ProcessLogin()", "#5.加入在線人員列表時發現已有同名帳號在里面. " + UserID + " [" + userToken.ConnectSocket.RemoteEndPoint + "]");
                        }
                        UserTokenList.Add(UserID, userToken);
                        //取消日志
                        //LogHelper.WriteLog("ProcessLogin()", "#6.已加入到在線人員列表. " + UserID + " [" + userToken.ConnectSocket.RemoteEndPoint + "]");
                        //System.Diagnostics.Debug.WriteLine(UserID + " Logged in at " + DateTime.Now.ToString("HH:mm:ss:fff"));
                        Done = true;
                    }
                }
            }
            return Done;
        }
예제 #2
0
        /// <summary>
        /// 執行狀態推送
        /// </summary>
        /// <param name="msgs"></param>
        /// <param name="MsgTo"></param>
        /// <param name="UserTokenList"></param>
        /// <returns></returns>
        private void PushUserState(List<byte[]> msgs, string MsgTo, SocketUserTokenList UserTokenList, int SendTimeout)
        {
            SocketUserToken recUser = UserTokenList[MsgTo] as SocketUserToken;
            if (recUser != null)
            {
                Socket userSkt = recUser.ConnectSocket;

                try
                {
                    if (userSkt.Connected)
                    {
                        //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                        lock (userSkt)
                        {
                            //Test:異步發送暫時不設置SendTimeout
                            //3秒不發不出去就跳過
                            //userSkt.SendTimeout = SendTimeout;
                            try
                            {
                                foreach (byte[] msg in msgs)
                                {
                                    //2016/05/19 test
                                    recUser.AsyncSendAgent.DoSendBuffer(msg);
                                    //userSkt.Send(msg);
                                    //SendData(userSkt, msg);
                                }
                            }
                            catch (SocketException ex)
                            {
                                throw ex;
                            }
                            finally
                            {
                                //userSkt.SendTimeout = 0;
                            }
                        }
                    }
                }
                catch (SocketException ex)
                {
                    throw ex;
                }
            }
        }
예제 #3
0
        /// <summary>
        /// 訂閱號服務端登錄
        /// </summary>
        /// <param name="UserID"></param>
        /// <param name="DataTerminalName"></param>
        /// <param name="DataGroup"></param>
        /// <param name="DataText"></param>
        /// <param name="userToken"></param>
        /// <param name="UserTokenList"></param>
        /// <returns></returns>
        private bool DoSubServiceLogin(string UserID, string DataTerminalName, string DataGroup, string DataText, SocketUserToken userToken, SocketUserTokenList UserTokenList)
        {
            bool Passed = true, Done = false;
            SocketUserToken ExistsUser = UserTokenList["#" + UserID + "#"];
            if (ExistsUser != null)
            {
                Socket curSkt = ExistsUser.ConnectSocket;
                string curIPAddress = ExistsUser.ConnectSocket.RemoteEndPoint.ToString();
                #region " 發送離線 "

                try
                {
                    List<byte[]> msgs = ParseProtocol.ConvertMsgToByte("00", "7", UserID, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper(), "");
                    //如果2秒內得不到之前登陸的對象,就直接干掉
                    //否則此帳號將永遠無法登錄
                    if (Monitor.TryEnter(curSkt, 2000))
                    {
                        try
                        {
                            //向用戶本人發送離線
                            foreach (byte[] msg in msgs)
                            {
                                //2016/05/19 test
                                ExistsUser.AsyncSendAgent.DoSendBuffer(msg);
                                //curSkt.Send(msg);
                                //SendData(curSkt, msg);
                            }
                        }
                        catch (SocketException ex)
                        {
                            LogHelper.WriteLog("DoSubServiceLogin()", "執行向" + DataGroup + "用戶: " + UserID + " [" + curIPAddress + "] 發送強制離線[不允許自動重連]消息時:" + (ex != null ? ex.Message : ""));
                        }
                        finally
                        {
                            Monitor.Exit(curSkt);
                        }
                    }
                    else
                    {
                        //如果到這里說明之前登陸的對象已經死鎖  
                        LogHelper.WriteLog("DoSubServiceLogin()", "嘗試使用Monitor.TryEnter鎖定" + DataGroup + "用戶: " + UserID + " [" + curIPAddress + "] 時失敗.");
                    }
                }
                catch (SocketException ex)
                {
                    LogHelper.WriteLog("DoSubServiceLogin()", "向" + DataGroup + "用戶: " + UserID + " [" + curIPAddress + "] 發送離線[不允許自動重連]消息時:" + (ex != null ? ex.Message : ""));
                }

                try
                {
                    //運行到這里時,有可能客戶端收到7-00之後主動斷開連接,則會觸發CloseClientSocket.
                    if (!ExistsUser.Closing)
                    {
                        //ExistsUser.Closing = true;
                        CloseClientSocket(ExistsUser);
                    }

                    LogHelper.WriteLog("DoSubServiceLogin", string.Format("因相同帳號再次登錄,強制先登錄的用戶{0} [{1}] 下線.", UserID, curIPAddress));

                    UpdateUserLog(UserID, "1", "0", "因相同帳號再次登陸而強制離線.", "", null);
                }
                catch (SocketException ex)
                {
                    LogHelper.WriteLog("DoSubServiceLogin()", "嘗試關閉" + DataGroup + "用戶: " + UserID + " [" + curIPAddress + "] 線程和Socket連接時出錯." + (ex != null ? ex.Message : ""));
                }

                #endregion
            }
            // 驗證是否為唯一用戶
            if (UserTokenList.ContainsKey("#" + UserID + "#"))
            {
                //到這里說明前面強制離線沒有成功
                try
                {
                    List<byte[]> msgs = ParseProtocol.ConvertMsgToByte("登錄失敗.", "3", UserID, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper(), "");
                    //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                    lock (userToken.ConnectSocket)
                    {
                        foreach (byte[] msg in msgs)
                        {
                            //同步發送
                            //2016/05/19 test
                            userToken.AsyncSendAgent.DoSendBuffer(msg);
                            //userToken.ConnectSocket.Send(msg);
                            //SendData(userToken.ConnectSocket, msg);
                        }
                    }
                    LogHelper.WriteLog("DoSubServiceLogin()", DataGroup + "用戶:" + UserID + "登錄失敗");
                }
                catch (SocketException ex)
                {
                    LogHelper.WriteLog("DoSubServiceLogin()", "發送登陸失敗信息時" + (ex != null ? ex.Message : ""));
                }
            }
            else
            {
                // 服務器開放登錄功能
                try
                {
                    List<byte[]> msgs = ParseProtocol.ConvertMsgToByte("登錄成功.", "2", UserID, DataTerminalName, DataGroup, Guid.NewGuid().ToString().Replace("-", "").ToUpper(), "");
                    //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                    lock (userToken.ConnectSocket)
                    {
                        foreach (byte[] msg in msgs)
                        {
                            //2016/05/19 test
                            userToken.AsyncSendAgent.DoSendBuffer(msg);
                            //userToken.ConnectSocket.Send(msg);
                            //SendData(userToken.ConnectSocket, msg);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Passed = false;
                    LogHelper.WriteLog("DoSubServiceLogin()", "發送登錄成功信息時" + (ex != null ? ex.Message : ""));
                }

                if (Passed)
                {
                    //設置對象狀態
                    userToken.BindingUser = new User();
                    userToken.BindingUser.State = User.UserStates.Online;
                    userToken.BindingUser.Role = User.UserRole.SubService;
                    userToken.BindingUser.Mobile = User.UserMobileType.None;
                    userToken.BindingUser.ID = UserID;
                    //Mac
                    userToken.BindingUser.MacAddr = DataTerminalName;

                    if (Passed)
                    {
                        //添加到正在執行的列表中
                        if (UserTokenList.ContainsKey("#" + UserID + "#"))
                        {
                            ExistsUser = UserTokenList["#" + UserID + "#"];
                            if (ExistsUser != null)
                            {
                                try
                                {
                                    LogHelper.WriteLog("DoSubServiceLogin", string.Format("加入在線人員列表時發現已有同名帳號在里面,強制用戶{0} [{1}] 下線.", UserID, ExistsUser.ConnectSocket.RemoteEndPoint));

                                    if (!ExistsUser.Closing)
                                    {
                                        //ExistsUser.Closing = true;
                                        CloseClientSocket(ExistsUser);
                                    }
                                }
                                catch (SocketException ex)
                                {
                                    LogHelper.WriteLog("DoSubServiceLogin()", "嘗試關閉" + DataGroup + "用戶" + UserID + "線程和Socket連接時出錯." + (ex != null ? ex.Message : ""));
                                }
                            }
                            //LogHelper.WriteLog("ProcessLogin()", "#5.加入在線人員列表時發現已有同名帳號在里面. " + UserID + " [" + userToken.ConnectSocket.RemoteEndPoint + "]");
                        }
                        UserTokenList.Add("#" + UserID + "#", userToken);
                        //取消日志
                        //LogHelper.WriteLog("ProcessLogin()", "#6.已加入到在線人員列表. " + UserID + " [" + userToken.ConnectSocket.RemoteEndPoint + "]");
                        //System.Diagnostics.Debug.WriteLine(UserID + " Logged in at " + DateTime.Now.ToString("HH:mm:ss:fff"));
                        Done = true;
                    }
                }
            }
            return Done;
        }
예제 #4
0
        public AsyncSocketServer()
        {
            SocketUserToken userToken;

            //服務器允許的最大連接數
            m_maxServerLoading = int.Parse((string)ConfigurationManager.AppSettings["MaxServerLoading"]);
            ServerStatistics.MaxServerLoading = m_maxServerLoading;

            //推送廣播間隔時間
            PushDataDelay = int.Parse((string)ConfigurationManager.AppSettings["PushDataDelay"]);
            //處理用戶在線狀態推送的線程數量
            MaxStateNotifyThreads = int.Parse((string)ConfigurationManager.AppSettings["MaxStateNotifyThreads"]);
            ServerStatistics.MaxUserState_PushQueue = MaxStateNotifyThreads;
            
            //抓DB信息
            string DBAlias = (string)ConfigurationManager.AppSettings["DB"];

            //縮略圖寬度
            ServerConst.Thumbnail_Width = int.Parse(ConfigurationManager.AppSettings["Thumbnail_Width"]);
            //縮略圖寬度
            ServerConst.Thumbnail_Height = int.Parse(ConfigurationManager.AppSettings["Thumbnail_Height"]);
            //縮略圖寬度
            ServerConst.Thumbnail_Quality = int.Parse(ConfigurationManager.AppSettings["Thumbnail_Quality"]);
            //同時開放多少個語音通話客戶端登錄
            ServerConst.AudioCall_Channels = int.Parse(ConfigurationManager.AppSettings["AudioCall_Channels"]);
            ServerStatistics.AudioCall_Channels = ServerConst.AudioCall_Channels;

            m_receiveBufferSize = ServerConst.ReceiveBufferSize;

            m_idleUserTokenPool = new SocketUserTokenPool(m_maxServerLoading);
            m_pcUserTokenList = new SocketUserTokenList();
            m_mobileUserTokenList = new SocketUserTokenList();
            m_fileUserTokenList = new SocketUserTokenList();
            m_appUserTokenList = new SocketUserTokenList();
            m_subServiceTokenList = new SocketUserTokenList();
            m_audioCallTokenList = new SocketUserTokenList();
            m_maxNumberAcceptedClients = new Semaphore(m_maxServerLoading, m_maxServerLoading);

            //按照連接數建立UserToken
            for (int i = 0; i < m_maxServerLoading; i++)
            {
                userToken = new SocketUserToken(m_receiveBufferSize);
                userToken.ReceiveEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
                userToken.SendEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
                m_idleUserTokenPool.Push(userToken);
            }

            this.CheckOS();
            this.DBInfo = RegHelper.GetDBInfo(DBAlias, RegURL);
        }
예제 #5
0
 /// <summary>
 /// 處理漫遊
 /// </summary>
 /// <param name="Sender"></param>
 /// <param name="msgs"></param>
 /// <param name="UserTokenList"></param>
 private void PushRoaming(string Sender, List<byte[]> msgs, SocketUserTokenList UserTokenList)
 {
     SocketUserToken recUser = UserTokenList[Sender] as SocketUserToken;
     if (recUser != null)
     {
         Socket userSkt = recUser.ConnectSocket;
         // 系統將訊息轉發給群成員(以發送者的帳號) 
         //問題: 1.只有帳號沒有姓名.Client無法顯示姓名
         //      2.沒有發送日期和時間
         try
         {
             //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
             lock (userSkt)
             {
                 foreach (byte[] msg in msgs)
                 {
                     //2016/05/19 test
                     recUser.AsyncSendAgent.DoSendBuffer(msg);
                     //userSkt.Send(msg);
                     //SendData(userSkt, msg);
                 }
             }
         }
         catch (SocketException ex)
         {
             try
             {
                 LogHelper.WriteLog("PushRoaming", "漫遊發群消息給用戶:" + Sender + "時發生異常,斷開連接." + (ex != null ? ex.Message : ""));
                 //主動關閉連接
                 //recUser.Closing = true;
                 //掉線了,直接干掉.
                 m_asyncSocketServer.CloseClientSocket(recUser);
             }
             catch
             { }
         }
     }
 }
예제 #6
0
        /// <summary>
        /// 執行消息推送
        /// </summary>
        /// <param name="Users"></param>
        /// <param name="msgs"></param>
        /// <param name="MsgTo"></param>
        /// <param name="UserTokenList"></param>
        /// <returns></returns>
        protected string PushMessage(string Users, List<byte[]> msgs, string MsgTo, SocketUserTokenList UserTokenList, string CommandDesc)
        {
            SocketUserToken recUser = UserTokenList[MsgTo] as SocketUserToken;
            if (recUser != null)
            {
                Socket userSkt = recUser.ConnectSocket;

                try
                {
                    if (userSkt.Connected)
                    {
                        //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息
                        lock (userSkt)
                        {
                            foreach (byte[] msg in msgs)
                            {
                                //2016/05/19 test
                                recUser.AsyncSendAgent.DoSendBuffer(msg);
                                //userSkt.Send(msg);
                                //SendData(userSkt, msg);
                            }
                        }

                        Users += "'" + MsgTo + "',";
                    }
                    else
                    {
                        LogHelper.WriteLog(CommandDesc + ".PushMessage", "用戶:" + MsgTo + "已斷開連接(Socket.Connected為false).");
                        //主動關閉連接
                        //recUser.Closing = true;
                        //掉線了,直接干掉.
                        m_asyncSocketServer.CloseClientSocket(recUser);
                    }
                }
                catch (SocketException ex)
                {
                    try
                    {
                        LogHelper.WriteLog(CommandDesc + ".PushMessage", "用戶:" + MsgTo + "異常斷開連接:" + (ex != null ? ex.Message : ""));
                        //主動關閉連接
                        //recUser.Closing = true;
                        //掉線了,直接干掉.
                        m_asyncSocketServer.CloseClientSocket(recUser);
                    }
                    catch
                    { }
                }
            }
            //else
            //{
            //    LogHelper.WriteLog(CommandDesc + ".PushMessage", "用戶:" + MsgTo + "不存在或未登錄.");
            //}
            return Users;
        }
예제 #7
0
        /// <summary>
        /// 得到指定客戶端的在線用戶清單
        /// </summary>
        /// <param name="UserTokenList"></param>
        /// <returns></returns>
        private string GetOnlineUserList(SocketUserTokenList UserTokenList)
        {
            string UserList = "";

            lock (UserTokenList.SyncRoot)
            {
                foreach (DictionaryEntry de in UserTokenList.Table)
                {
                    UserList += de.Key.ToString() + ",";
                }
            }

            return UserList;
        }