/// <summary> /// /// </summary> /// <param name="UserID"></param> /// <param name="conn"></param> /// <param name="logType">0=login;1=logout;2=signature</param> /// <param name="logDevice"></param> private void UpdateUserLog(string UserID, string logType, string logDevice, string logText) { using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { DoUpdateUserLog(conn, UserID, logType, logDevice, logText); conn.CloseConnection(); } catch (Exception ex) { conn.CloseConnection(); throw ex; } } }
//2016/03/03 /// <summary> /// 更新數據類群信息 /// </summary> private void UpdateVDataThreadFunc() { //Test //VDataQueue.Enqueue("iemis.UpdateVData 'D151000001',N'這是一條測試數據,这是一条测试数据555.','2016/06/03','10:20:30'"); bool TryOpenConn = false; int TryCount = 0; SQLHelper conn = new SQLHelper(DBInfo); try { conn.OpenConnection(); while (true) { Thread.Sleep(1000); try { //當前設備數據更新隊列 ServerStatistics.CurentDeviceData_Queue = VDataQueue.Count; //最高設備數據更新隊列 if (ServerStatistics.MaxDeviceData_Queue < ServerStatistics.CurentDeviceData_Queue) ServerStatistics.MaxDeviceData_Queue = ServerStatistics.CurentDeviceData_Queue; if (TryOpenConn) { try { conn.OpenConnection(); TryOpenConn = false; //成功连接 LogHelper.WriteLog("UpdateVDataThreadFunc()", "重新连接数据库成功."); TryCount = 0; } catch { //尝试重新连接超过180次(3分钟内不恢复) TryCount++; } if (TryCount > 180) { LogHelper.WriteLog("UpdateVDataThreadFunc()", "尝试重新连接数据库次数达到" + TryCount.ToString() + "次仍然无法成功,更新作业被迫中止.请检查数据库状态和网络连接."); break; } } while (VDataQueue.Count > 0) { conn.ExecuteSQL(VDataQueue.Dequeue().ToString()); } } catch (Exception ex) { //发生异常有可能是数据库连接断开.标记下一次执行时尝试重新连接 TryOpenConn = true; LogHelper.WriteLog("UpdateVDataThreadFunc()", "更新數據類群信息時:" + (ex != null ? ex.Message : "")); } } } catch (Exception ex) { LogHelper.WriteLog("UpdateVDataThreadFunc()", "更新數據類群信息時:" + (ex != null ? ex.Message : "")); } finally { if (conn != null) conn.CloseConnection(); } }
//private bool CloseBothSide(string curUserID, bool send711) //{ // //接收數據時發生異常,被置空.從哈希表中移除 // try // { // #region " 一方異常斷開則通知另一方后自動斷開另一方 " // string tChannelGUID = curUserID.Substring(0, curUserID.Length - 2); // //發送人姓名(發起方和接聽方都記錄的相同名稱) // string DataTerminalName = m_userToken.BindingUser.Name; // //發送者ID-接收者ID-GUID-R/S // string Target = "", sChannelID = ""; // if (curUserID.Substring(curUserID.Length - 1, 1) == "S") // { // Target = tChannelGUID + "-R"; // sChannelID = m_userToken.BindingUser.ReceiverID; // } // else // { // Target = tChannelGUID + "-S"; // sChannelID = m_userToken.BindingUser.SenderID; // } // //通話A方時長 // if (!send711) // { // //記錄日誌 // try // { // //S通道對象 // SocketUserToken TargetA = m_asyncSocketServer.PcUserTokenList[m_userToken.BindingUser.SenderID] as SocketUserToken; // SocketUserToken TargetB = m_asyncSocketServer.PcUserTokenList[m_userToken.BindingUser.ReceiverID] as SocketUserToken; // string SIP = "", DevSName = "", SMacAddr = "", RIP = "", DevRName = "", RMacAddr = ""; // if (TargetA != null && TargetA.BindingUser != null) // { // SIP = TargetA.BindingUser.IP; // DevSName = TargetA.BindingUser.DevName; // SMacAddr = TargetA.BindingUser.MacAddr; // } // if (TargetB != null && TargetB.BindingUser != null) // { // RIP = TargetB.BindingUser.IP; // DevRName = TargetB.BindingUser.DevName; // RMacAddr = TargetB.BindingUser.MacAddr; // } // UpdateAudioLog(m_userToken.BindingUser.SenderID, m_userToken.BindingUser.ReceiverID, // m_userToken.ConnectDateTime, m_userToken.ActiveDateTime, tChannelGUID, // SIP, DevSName, SMacAddr, RIP, DevRName, RMacAddr); // } // catch // { } // } // SocketUserToken TargetUser = m_asyncSocketServer.AudioCallTokenList[Target] as SocketUserToken; // if (TargetUser != null) // { // //主動關閉T通道連接 // m_asyncSocketServer.CloseClientSocket(TargetUser); // } // //再用S通道通知對方7-11(由於對方連線異常斷開導致通話中斷.) // if (send711) // { // base.PushMessage("", // ParseProtocol.ConvertMsgToByte("11", "7", curUserID, "AudioUser", "", tChannelGUID, "-1"), // sChannelID, m_asyncSocketServer.PcUserTokenList, "CloseBothSide"); // } // else // { // //發送通話時長消息 // using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) // { // conn.OpenConnection(); // try // { // // 記錄到數據庫中 // string DataGUID = Guid.NewGuid().ToString().Replace("-", "").ToUpper(); // string DataBody = "本次通話時長: " + (int)m_userToken.ActiveDateTime.Subtract(m_userToken.ConnectDateTime).TotalSeconds + "秒."; // string MsgNO = this.InsertMsg(conn, m_userToken.BindingUser.SenderID, DataBody, "", m_userToken.BindingUser.ReceiverID, "1", DataGUID, false, true); // if (MsgNO.Length > 0) // { // //開始發送 // base.SendP2PMessage(m_userToken.BindingUser.SenderID, DataTerminalName, m_userToken.BindingUser.ReceiverID, DataBody, conn, DataGUID, MsgNO, "U"); // } // conn.CloseConnection(); // } // catch // { // conn.CloseConnection(); // } // } // } // #endregion // } // catch // { } // // 斷開發送者(S) // //主動關閉連接 // //m_userToken.Closing = true; // return false; //} /// <summary> /// 斷開T通道兩端用戶 /// </summary> public override void ProcessUserDisconnected() { try { //即將斷開連接的用戶ID string curUserID = m_userToken.BindingUser.ID; //T通道GUID string tChannelGUID = curUserID.Substring(0, curUserID.Length - 2); //發送人姓名(發起方和接聽方都記錄的相同名稱) string DataTerminalName = m_userToken.BindingUser.Name; //發送者ID-接收者ID-GUID-R/S string Target = "", Role = ""; if (curUserID.Substring(curUserID.Length - 1, 1) == "S") { Target = tChannelGUID + "-R"; Role = "S"; } else { Target = tChannelGUID + "-S"; Role = "R"; } if (Role == "S") { #region " 記錄日誌 " try { //S通道對象 SocketUserToken TargetA = m_asyncSocketServer.PcUserTokenList[m_userToken.BindingUser.SenderID] as SocketUserToken; SocketUserToken TargetB = m_asyncSocketServer.PcUserTokenList[m_userToken.BindingUser.ReceiverID] as SocketUserToken; string SIP = "", DevSName = "", SMacAddr = "", RIP = "", DevRName = "", RMacAddr = ""; if (TargetA != null && TargetA.BindingUser != null) { SIP = TargetA.BindingUser.IP; DevSName = TargetA.BindingUser.DevName; SMacAddr = TargetA.BindingUser.MacAddr; } if (TargetB != null && TargetB.BindingUser != null) { RIP = TargetB.BindingUser.IP; DevRName = TargetB.BindingUser.DevName; RMacAddr = TargetB.BindingUser.MacAddr; } UpdateAudioLog(m_userToken.BindingUser.SenderID, m_userToken.BindingUser.ReceiverID, m_userToken.ConnectDateTime, m_userToken.ActiveDateTime, tChannelGUID, SIP, DevSName, SMacAddr, RIP, DevRName, RMacAddr); } catch (Exception ex) { LogHelper.WriteLog("AudioCallProcessor.CloseBothSide", "記錄通話日誌時出錯:" + (ex != null ? ex.Message : "")); } #endregion } if (Role == "S") { //發送通話時長消息 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 int TotalSeconds = (int)m_userToken.ActiveDateTime.Subtract(m_userToken.ConnectDateTime).TotalSeconds; int Hours = 0, Minutes = 0, Seconds = 0; Seconds = TotalSeconds % 60; Minutes = ((TotalSeconds - Seconds) / 60) % 60; Hours = (TotalSeconds - Seconds) / 3600; string DataGUID = Guid.NewGuid().ToString().Replace("-", "").ToUpper(); string DataBody = "本次通話時長: " + Hours.ToString().PadLeft(2, '0') + ":" + Minutes.ToString().PadLeft(2, '0') + ":" + Seconds.ToString().PadLeft(2, '0'); string MsgNO = this.InsertMsg(conn, m_userToken.BindingUser.SenderID, DataBody, "", m_userToken.BindingUser.ReceiverID, "1", DataGUID, false, true); if (MsgNO.Length > 0) { //開始發送 base.SendP2PMessage(m_userToken.BindingUser.SenderID, DataTerminalName, m_userToken.BindingUser.ReceiverID, DataBody, conn, DataGUID, MsgNO, "U"); } conn.CloseConnection(); } catch (Exception ex) { conn.CloseConnection(); LogHelper.WriteLog("AudioCallProcessor.CloseBothSide", "發送通話時長時發生錯誤:" + (ex != null ? ex.Message : "")); } } } } catch { } }
/// <summary> /// /// </summary> /// <param name="UserID"></param> /// <param name="conn"></param> /// <param name="State"></param> public void UpdateUserState(string UserID, string State) { using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { DoUpdateUserState(conn, UserID, State); conn.CloseConnection(); } catch (Exception ex) { conn.CloseConnection(); throw ex; } } }
//2016/02/27 /// <summary> /// 標記歷史消息為已讀 /// </summary> private void MarkReadThreadFunc() { bool TryOpenConn = false; int TryCount = 0; SQLHelper conn = new SQLHelper(DBInfo); try { conn.OpenConnection(); while (true) { Thread.Sleep(1000); try { //當前歷史消息標記已讀隊列 ServerStatistics.CurentMarkRead_Queue = MarkReadHistoryMsgQueue.Count; //最高歷史消息標記已讀隊列 if (ServerStatistics.MaxMarkRead_Queue < ServerStatistics.CurentMarkRead_Queue) ServerStatistics.MaxMarkRead_Queue = ServerStatistics.CurentMarkRead_Queue; if (TryOpenConn) { try { conn.OpenConnection(); TryOpenConn = false; //成功连接 LogHelper.WriteLog("MarkReadThreadFunc()", "重新连接数据库成功."); TryCount = 0; } catch { //尝试重新连接超过180次(3分钟内不恢复) TryCount++; } if (TryCount > 180) { LogHelper.WriteLog("MarkReadThreadFunc()", "尝试重新连接数据库次数达到" + TryCount.ToString() + "次仍然无法成功,更新作业被迫中止.请检查数据库状态和网络连接."); break; } } while (MarkReadHistoryMsgQueue.Count > 0) { conn.ExecuteSQL(MarkReadHistoryMsgQueue.Dequeue().ToString()); } } catch (Exception ex) { //发生异常有可能是数据库连接断开.标记下一次执行时尝试重新连接 TryOpenConn = true; LogHelper.WriteLog("MarkReadThreadFunc()", "標記歷史消息為已讀:" + (ex != null ? ex.Message : "")); } } } catch (Exception ex) { LogHelper.WriteLog("MarkReadThreadFunc()", "標記歷史消息為已讀:" + (ex != null ? ex.Message : "")); } finally { if (conn != null) conn.CloseConnection(); } }
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; }
/// <summary> /// /// </summary> /// <param name="UserID"></param> /// <param name="conn"></param> /// <param name="logType">0=login;1=logout;2=signature</param> /// <param name="logDevice"></param> public void UpdateUserLog(string UserID, string logType, string logDevice, string logText, string logIP, byte[] logAvatar) { using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { DoUpdateUserLog(conn, UserID, logType, logDevice, logText, logIP, "", "", logAvatar); conn.CloseConnection(); } catch (Exception ex) { conn.CloseConnection(); throw ex; } } }
private void btnStart_Click(object sender, EventArgs e) { try { string SrvNOs = ""; ListViewItem lvi = listSubSrvs.SelectedItems[0]; //foreach (ListViewItem lvi in listSubSrvs.Items) //{ if (lvi.SubItems[1].Text == "0") { ClientSocket clientSocket = new ClientSocket(GetLX_IP(IP.Text), Convert.ToInt32(Port.Text)); clientSocket.Connect(true); clientSocket.ReciveMsg -= subSrv_ReciveMsg; clientSocket.ReciveMsg += subSrv_ReciveMsg; clientSocket.GroupID = lvi.SubItems[0].Text; clientSocket.Send("SubSrv logged in", "0", clientSocket.GroupID, "mac", "SUB", Guid.NewGuid().ToString().ToString().Replace("-", "").ToUpper()); if (SubServices.Contains(clientSocket.GroupID)) { //斷開原來的連接 try { ClientSocket oldClientSocket = SubServices[clientSocket.GroupID] as ClientSocket; oldClientSocket.Disconnect(); oldClientSocket.Dispose(); } catch { } SubServices.Remove(clientSocket.GroupID); } SubServices.Add(clientSocket.GroupID, clientSocket); //記錄已開啟的訂閱呺 SrvNOs += "'" + lvi.SubItems[0].Text + "',"; } //} //更新訂閱號狀態 if (SrvNOs.Length > 0) { using (SQLHelper conn = new SQLHelper(DBAlias)) { conn.OpenConnection(); try { SrvNOs = SrvNOs.Substring(0, SrvNOs.Length - 1); // 標記為已讀 DateTime now = DateTime.Now; string ymd = now.ToString("yyyy/MM/dd"); string time = now.ToString("HH:mm:ss"); conn.ExecuteSQL("update a set a.srv_state='1',a.ie_lymd='" + ymd + "',a.ie_ltime='" + time + "' from lxsubsrvs a where a.srv_no in (" + SrvNOs + ")"); conn.CloseConnection(); } catch { conn.CloseConnection(); } } } //刷新列表 btnRefresh_Click(sender, e); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
/// <summary> /// 群異動系統消息 /// </summary> /// <param name="Sender"></param> /// <param name="ToGroup"></param> /// <param name="MsgGUID"></param> /// <param name="MsgText"></param> protected void SendGroupSysMessage(string Sender, string ToGroup, string MsgGUID, string MsgText) { // 抓出群成員 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 string MsgNO = this.InsertMsg(conn, Sender, MsgText, ToGroup, "", "0", MsgGUID, false, true); DataTable UserList = conn.OpenDataTable("select a.msg_to from lrmsgstate a (nolock) where a.msg_no=" + MsgNO + " and a.msg_state='0'", CommandType.Text); if (UserList.Rows.Count > 0) { string Users = ""; // PC 和 Mobile 要用到的信息.提前打包好,沒必要放到for循環里去做 List<byte[]> msgs = ParseProtocol.ConvertMsgToByte(MsgText, "5", "", "", ToGroup, MsgGUID, MsgNO); // Web 要用到的信息.提前打包好,沒必要放到for循環里去做 - 暫時不實現 //byte[] msgw = WebConvertMethod.ConvertMsgToByte(DataBody, "5", "", "", DataGroup, MsgNO); foreach (DataRow User in UserList.Rows) { //有沒有必要PC和MOBLIE端各開個一個欄位來存放消息是否讀取的標記? #region " PC Client " Users = PushMessage(Users, msgs, User["msg_to"].ToString(), m_asyncSocketServer.PcUserTokenList, "SendGroupSysMessage"); #endregion #region " Mobile Client " Users = PushMessage(Users, msgs, User["msg_to"].ToString(), m_asyncSocketServer.MobileUserTokenList, "SendGroupSysMessage"); #endregion #region " Web Client - 暫時不實現" //recUser = _ws_transmit_tb[User["msg_to"].ToString()] as UserSocket; //if (recUser != null) //{ // Socket userSkt = recUser.Socket; // try // { // //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 // lock (userSkt) // { // userSkt.Send(msgw); // //SendData(userSkt, msg); // } // Users += "'" + User["msg_to"].ToString() + "',"; // } // catch (SocketException ex) // { // LogHelper.WriteLog("SendGroupSysMessage", "手機用戶:" + User["msg_to"].ToString() + "異常斷開連接:" + (ex != null ? ex.Message : "")); // try // { // //掉線了,直接干掉. // if (userSkt.Connected) // { // userSkt.Shutdown(SocketShutdown.Both); // //userSkt.Disconnect(false); // } // userSkt.Close(); // #region " 聯絡人狀態變更 " // //如果PC端沒在線就通知聯絡人此人離線了 // ProcessWebUserState(recUser); // #endregion // lock (_ws_transmit_tb.SyncRoot) // _ws_transmit_tb.Remove(User["msg_to"].ToString()); // Thread userThread = _ws_thread_tb[User["msg_to"].ToString()] as Thread; // userThread.Abort(); // //線程池不會被遍歷,不鎖. // _ws_thread_tb.Remove(User["msg_to"].ToString()); // } // catch // { } // } //} #endregion } // 去掉最後一個逗號 if (Users.Length > 0) { Users = Users.Substring(0, Users.Length - 1); // 標記為已讀 DateTime now = DateTime.Now; string ymd = now.ToString("yyyy/MM/dd"); string time = now.ToString("HH:mm:ss"); conn.ExecuteSQL("update a set a.msg_state='1',a.ie_lymd='" + ymd + "',a.ie_ltime='" + time + "' from lrmsgstate a where a.msg_no=" + MsgNO + " and a.msg_state='0' and a.msg_to in (" + Users + ")"); } } UserList.Dispose(); UserList = null; conn.CloseConnection(); #region " 向發送者發送回執7-03 " PushFeedback(MsgGUID, MsgNO); #endregion #region " 處理同帳號設備之間發送的消息漫遊 " //處理同一帳號多個端登錄的轉發. if (m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.PC || m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.APP) { //來自PC端消息. //檢查相同帳號Mobile(Web)端有沒有登錄,有就轉發一次. #region " Mobile Client " PushRoaming(Sender, ParseProtocol.ConvertMsgToByte(MsgText, "5", "", "", ToGroup, MsgGUID, MsgNO, "R"), m_asyncSocketServer.MobileUserTokenList); #endregion } if (m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.Mobile || m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.APP) { //來自Mobile(Web)端消息. //檢查相同帳號Web端有沒有登錄,有就轉發一次. #region " PC Client " PushRoaming(Sender, ParseProtocol.ConvertMsgToByte(MsgText, "5", "", "", ToGroup, MsgGUID, MsgNO, "R"), m_asyncSocketServer.PcUserTokenList); #endregion } #endregion } catch { conn.CloseConnection(); } } }
private void btnRefresh_Click(object sender, EventArgs e) { listSubSrvs.Items.Clear(); using (SQLHelper conn = new SQLHelper(DBAlias)) { conn.OpenConnection(); try { string SQL = "select * from lxsubsrvs (nolock) where srv_device = '" + Device + "'"; DataTable Rec = conn.OpenDataTable(SQL, CommandType.Text); conn.CloseConnection(); foreach (DataRow row in Rec.Rows) { ListViewItem lvi = new ListViewItem(new string[2] { row["srv_no"].ToString(), row["srv_state"].ToString() }); listSubSrvs.Items.Add(lvi); } Rec.Dispose(); Rec = null; } catch { conn.CloseConnection(); } } }
private void MainUI_FormClosed(object sender, FormClosedEventArgs e) { try { lock (SubServices.SyncRoot) { foreach (DictionaryEntry de in SubServices) { ClientSocket subSrv = de.Value as ClientSocket; if (subSrv != null && subSrv.Connected) { try { subSrv.Send("SubSrv logged out", "1", subSrv.GroupID, "mac", "SUB", Guid.NewGuid().ToString().ToString().Replace("-", "").ToUpper()); subSrv.Disconnect(); subSrv.ReciveMsg -= subSrv_ReciveMsg; subSrv.Dispose(); } catch { } } } } using (SQLHelper conn = new SQLHelper(DBAlias)) { conn.OpenConnection(); try { // 標記為已讀 DateTime now = DateTime.Now; string ymd = now.ToString("yyyy/MM/dd"); string time = now.ToString("HH:mm:ss"); conn.ExecuteSQL("update a set a.srv_state='0',a.ie_lymd='" + ymd + "',a.ie_ltime='" + time + "' from lxsubsrvs a where srv_device = '" + Device + "' and srv_state = '1'"); conn.CloseConnection(); } catch { conn.CloseConnection(); } } SubServices.Clear(); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
private void btnStop_Click(object sender, EventArgs e) { try { ListViewItem lvi = listSubSrvs.SelectedItems[0]; if (SubServices[lvi.SubItems[0].Text] != null) { ClientSocket subSrv = SubServices[lvi.SubItems[0].Text] as ClientSocket; if (subSrv != null && subSrv.Connected) { try { subSrv.Send("SubSrv logged out", "1", subSrv.GroupID, "mac", "SUB", Guid.NewGuid().ToString().ToString().Replace("-", "").ToUpper()); subSrv.Disconnect(); subSrv.ReciveMsg -= subSrv_ReciveMsg; subSrv.Dispose(); } catch { } } using (SQLHelper conn = new SQLHelper(DBAlias)) { conn.OpenConnection(); try { // 標記為已讀 DateTime now = DateTime.Now; string ymd = now.ToString("yyyy/MM/dd"); string time = now.ToString("HH:mm:ss"); conn.ExecuteSQL("update a set a.srv_state='0',a.ie_lymd='" + ymd + "',a.ie_ltime='" + time + "' from lxsubsrvs a where srv_device = '" + Device + "' and srv_no ='" + lvi.SubItems[0].Text + "'"); conn.CloseConnection(); } catch { conn.CloseConnection(); } } SubServices.Remove(lvi.SubItems[0].Text); //刷新列表 btnRefresh_Click(sender, e); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
/// <summary> /// 處理命令 /// </summary> /// <returns></returns> public override bool ProcessCommand(SocketUserToken userToken) { //開始解包 DynamicBufferManager receiveBuffer = userToken.ReceiveBuffer; string curUserID = userToken.BindingUser.ID; string curDevice = (userToken.BindingUser.Role == User.UserRole.PC ? "PC客戶端" : "Mobile客戶端"); try { //返回解包后的資料(返回數組 0=type ; 1=終端; 2=群號; 3=時間; 4=消息ID; 5=消息內容 6=終端姓名 7=消息系統編號 8=設置漫遊) int msgDataLength = 0; object[] ReceiveData = ParseProtocol.UnpackMsgPackage(receiveBuffer.Buffer, out msgDataLength); string DataType = ReceiveData[0].ToString(); //如果數據類別為空就踢出 if (DataType == "") { LogHelper.WriteLog("PcProcessor.ProcessCommand", "讀取" + curDevice + "用戶: @<" + curUserID + " " + userToken.ConnectSocket.RemoteEndPoint + "> 數據時連接異常斷開."); //主動關閉連接 //userToken.Closing = true; return false; } string DataTerminal = ReceiveData[1].ToString(); string DataGroup = ReceiveData[2].ToString(); string DataGUID = ReceiveData[4].ToString(); string DataBody = ((DataType != "I" && DataType != "R") ? ReceiveData[5].ToString() : "N/A"); // 非屏幕截圖時才有值 byte[] DataImage = ((DataType == "I" || DataType == "R") ? (byte[])ReceiveData[5] : null); // 屏幕截圖時才有值 string DataTerminalName = ReceiveData[6].ToString(); //Added by Donnie on 2016/04/27 //如果是換頭像也不會有值 if (DataType == "S" && DataTerminalName == "8") { DataBody = "N/A"; DataImage = (byte[])ReceiveData[5]; } // 分類處理 switch (DataType) { case "1": #region " 用戶離線 " LogHelper.WriteLog("PcProcessor.ProcessCommand", curDevice + "用戶: @<" + curUserID + " " + userToken.ConnectSocket.RemoteEndPoint + "> 離線."); #endregion //主動關閉連接 //userToken.Closing = true; return false; case "5": #region " 群(異動)系統訊息 " base.SendGroupSysMessage(DataTerminal, DataGroup, DataGUID, DataBody); #endregion break; case "6": #region " 心跳包 " base.DoAlive(DataTerminal, DataBody, DataType, DataGUID); #endregion break; case "7": #region " 控制臺消息(7-07/7-08) " base.ProcessConsoleCommands(DataBody); #endregion break; case "8": #region " 發送在線用戶ID清單 " base.PushOnlineUserList(DataGroup, DataType, DataGUID); #endregion break; case "B": #region " 系統廣播/公告 - 管理員專用 " try { //DataTerminal:命令(1=播放;0=停止) //DataTerminalName: 項次 //DataGroup: 區域(ALL=全服播放;代號=單區播放) //DataBody: 公告內容 //using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) //{ // conn.OpenConnection(); // try // { // if (conn.OpenDataTable("select uid from lrbroadcast (nolock) where region_id = '" + DataGroup + "' and bdc_seq = '" + DataTerminalName + "'", CommandType.Text).Rows.Count > 0) // { // //有資料 // conn.ExecuteSQL("update a set a.bdc_cmd='" + DataTerminal + "',a.bdc_text=N'" + DataBody + "' from lrbroadcast a where a.region_id = '" + DataGroup + "' and a.bdc_seq = '" + DataTerminalName + "'"); // } // else // { // //沒資料 // if (DataTerminal == "1") // { // conn.ExecuteSQL("insert into lrbroadcast (region_id,bdc_seq,bdc_text,bdc_cmd) values('" + DataGroup + "','" + DataTerminalName + "',N'" + DataBody + "','" + DataTerminal + "')"); // } // } // conn.CloseConnection(); // } // catch // { // conn.CloseConnection(); // } //} ////1.更新公告內容和區域 //lock (base.m_asyncSocketServer.SysNotices.SyncRoot) //{ // if (base.m_asyncSocketServer.SysNotices.ContainsKey(DataGroup)) // { // //ALL 也會存里面 // List<NoticeMsg> nMsgs = (List<NoticeMsg>)base.m_asyncSocketServer.SysNotices[DataGroup]; // NoticeMsg nMsg = nMsgs.Find(delegate(NoticeMsg _msg) { return _msg.MsgSeq == DataTerminalName; }); // if (nMsg != null) // { // if (DataTerminal == "1") // { // // 替換現有的公告 // nMsg.MsgText = DataBody; // } // else // { // // 移除現有的公告 // nMsgs.Remove(nMsg); // if (nMsgs.Count == 0) // { // // 當前區域沒有公告了,將區域移除 // base.m_asyncSocketServer.SysNotices.Remove(DataGroup); // } // } // } // else // { // if (DataTerminal == "1") // { // // 新公告 // nMsgs.Add(new NoticeMsg() { MsgSeq = DataTerminalName, MsgText = DataBody }); // } // } // } // else // { // if (DataTerminal == "1") // { // //新公告 // base.m_asyncSocketServer.SysNotices.Add(DataGroup, new List<NoticeMsg>() { new NoticeMsg() { MsgSeq = DataTerminalName, MsgText = DataBody } }); // } // } //} //2.向區域內的用戶播放 base.SendSysNotice(DataTerminal, DataTerminalName, DataGroup, DataBody); } catch (Exception ex) { LogHelper.WriteLog("PcProcessor.ProcessCoommand", "發送服務器廣播時:" + (ex != null ? ex.Message : "")); } #endregion break; case "H": #region " 發送服務器健康報告 " try { //[#1]:120 [PC端用戶] //[#2]:12 [移動端用戶] //[#3]:10 [訂閱號服務端] //[#4]:12/50 [空閒UserToken] //[#5]:10 [APP用戶] //[#6]:2 [文件傳送用戶] //[#7]:0 [歷史消息標記已讀隊列] //[#8]:89 [用戶狀態推送隊列] //[#9]:0/10 [空間狀態推送線程] //[#10]:10 [設備數據更新隊列] //[#11]:10 [語音通話客戶] DataBody = ""; //[PC端用戶] DataBody += "[#1]:" + m_asyncSocketServer.PcUserTokenList.Count.ToString() + "|"; //[移動端用戶] DataBody += "[#2]:" + m_asyncSocketServer.MobileUserTokenList.Count.ToString() + "|"; //[訂閱號服務端] DataBody += "[#3]:" + m_asyncSocketServer.SubServiceTokenList.Count.ToString() + "|"; //[空閒UserToken] DataBody += "[#4]:" + m_asyncSocketServer.IdleUserTokenPool.Count.ToString() + "/" + m_asyncSocketServer.MaxServerLoading.ToString() + "|"; //[APP用戶] DataBody += "[#5]:" + m_asyncSocketServer.AppUserTokenList.Count.ToString() + "|"; //[文件傳送用戶] DataBody += "[#6]:" + m_asyncSocketServer.FileUserTokenList.Count.ToString() + "|"; //[歷史消息標記已讀隊列] DataBody += "[#7]:" + m_asyncSocketServer.MarkReadHistoryMsgQueue.Count.ToString() + "|"; //[用戶狀態推送隊列] DataBody += "[#8]:" + m_asyncSocketServer.StateNotifyQueue.Count.ToString() + "|"; //[空間狀態推送線程] DataBody += "[#9]:" + m_asyncSocketServer.StateNofityThreadsQueue.Count.ToString() + "/" + m_asyncSocketServer.MaxStateNotifyThreads.ToString() + "|"; //[設備數據更新隊列] DataBody += "[#10]:" + m_asyncSocketServer.VDataQueue.Count.ToString() + "|"; //[語音通話客戶] DataBody += "[#11]:" + m_asyncSocketServer.AudioCallTokenList.Count.ToString(); List<byte[]> msgs = ParseProtocol.ConvertMsgToByte(DataBody, DataType, DataTerminal, DataTerminalName, "", DataGUID); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (userToken.ConnectSocket) { foreach (byte[] msg in msgs) { //2016/05/19 test userToken.AsyncSendAgent.DoSendBuffer(msg); //userToken.ConnectSocket.Send(msg); //base.SendData(userToken.ConnectSocket, msg); } } //clsClientLog.WriteLog(clsClientLog.LogType.Info, "ThreadFunc(object obj):default", "成功向: " + _receiver + " 發送信息: " + _packetBuff); } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送在線用戶ID清單時:" + ex.Message); LogHelper.WriteLog("PcProcessor.ProcessCoommand", "發送服務器健康報告時時:" + (ex != null ? ex.Message : "")); } #endregion break; case "C": #region " 群命令 " // 抓出群成員 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 //DateTime MsgDT = DateTime.Now; string MsgNO = this.InsertCmd(conn, DataTerminal, DataBody, DataGroup, DataGUID); if (MsgNO.Length > 0) { // 向管理員發的命令不轉發 if (DataGroup.Length > 0) { //系統將命令轉發給群成員(以發送者的帳號) base.SendGroupCommand(DataTerminal, DataGroup, DataBody, DataTerminalName, conn, DataGUID, MsgNO); } // 轉發完再發回執 // 向發送者發送回執7-03 // 回執給PC端里,必須用DataGUID,因為PC端本地生成的GUID要和這個DataGUID匹配 base.PushFeedback(DataGUID, MsgNO); } conn.CloseConnection(); } catch { conn.CloseConnection(); } } #endregion break; case "D": #region " 撤回消息 " //0001D發送人帳號(50b)接收對象類別(U=人;G=群)(60b)接收人/接收群(50b)GMT時間(20b)要撤回消息的GUID(32b)訊息流水號(20b) using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中(1=撤回,M=消息lrmsg) string MsgNO = this.InsertSysMsg(conn, DataTerminal, DataBody, "1", "M", (DataTerminalName == "G" ? DataGroup : ""), (DataTerminalName == "U" ? DataGroup : ""), DataGUID); if (MsgNO.Length > 0) { //系統將訊息轉發給群成員(以發送者的帳號) base.SendGroupSysBroadcast("D", "1", "M", DataTerminal, DataGroup, DataBody, DataTerminalName, conn, DataGUID, MsgNO); // 轉發完再發回執 // 向發送者發送回執7-03 base.PushFeedback(DataGUID, MsgNO); } conn.CloseConnection(); } catch { conn.CloseConnection(); } } #endregion break; case "G": case "L": #region " 群組訊息(G=Push / L=Pull) " base.SendGroupBroadcast(DataTerminal, DataGroup, DataBody, DataTerminalName, DataGUID, DataType == "G"); #endregion break; case "I": #region " 轉發屏幕截圖 " //DataTerminal是接收人帳號(對人) //DataTerminal是發送人帳號(對群) //DataTerminalName是發送人姓名 base.SendImage(DataTerminal, DataGroup, DataImage, DataTerminalName, DataGUID); #endregion break; case "U": //人對人信息 case "T": //測試工具使用 #region " 用戶訊息 " //別搞暈了 //DataTerminal是接收人帳號 //DataTerminalName是發送人姓名 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 //DateTime MsgDT = DateTime.Now; //T=測試用(超哥神器) string MsgNO = this.InsertMsg(conn, curUserID, DataBody, "", DataTerminal, "1", DataGUID, DataType == "T", true); if (MsgNO.Length > 0) { //開始發送 base.SendP2PMessage(curUserID, DataTerminalName, DataTerminal, DataBody, conn, DataGUID, MsgNO, DataType); // 轉發完再發回執 // 向發送者發送回執7-03 base.PushFeedback(DataGUID, MsgNO); } conn.CloseConnection(); } catch { conn.CloseConnection(); } } #endregion break; case "Q": //抖動 #region " 抖動 " //DataTerminal是接收人帳號 //DataTerminalName是發送人姓名 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 //DateTime MsgDT = DateTime.Now; string MsgNO = this.InsertMsg(conn, curUserID, DataBody, "", DataTerminal, "1", "", "5", "0", DataGUID, false, true); if (MsgNO.Length > 0) { //開始發送 base.SendP2PMessage(curUserID, DataTerminalName, DataTerminal, DataBody, conn, DataGUID, MsgNO, DataType); // 轉發完再發回執 // 向發送者發送回執7-03 base.PushFeedback(DataGUID, MsgNO); } conn.CloseConnection(); } catch { conn.CloseConnection(); } } #endregion break; case "R": #region " 轉發錄音 " //DataTerminal是接收人帳號(對人) //DataTerminal是發送人帳號(對群) //DataTerminalName是發送人姓名 //ReceiveData[7].ToString()是語音時長 base.SendVoice(DataTerminal, DataGroup, DataImage, DataTerminalName, DataGUID, ReceiveData[7].ToString()); #endregion break; case "S": #region " 聯絡人狀態變更 " //通知在線的聯絡人當前用戶改變了狀態 //0=空閒|1=上線|2=離開|3=忙碌|4=不要打擾|5=隱身|6=離線|7=簽名|8=換頭像 userToken.BindingUser.SetUserState(DataTerminalName); //特殊處理簽名操作 if (DataTerminalName == "7") { //User.ChangeSignature = true; userToken.BindingUser.Signature = DataBody; //signature m_asyncSocketServer.UpdateUserLog(curUserID, "2", "0", userToken.BindingUser.Signature, "", null); } else if (DataTerminalName == "8") { //Added by Donnie on 2016/04/27 // 變更頭像的處理 m_asyncSocketServer.UpdateUserLog(curUserID, "3", "0", "更新頭像", "", DataImage); } //Added by Donnie on 2016/04/27 //ID,狀態,簽名,聯絡人清單,頭像數據 if (userToken.BindingUser.Contacts.Count > 0) m_asyncSocketServer.StateNotifyQueue.Enqueue(new List<object>() { curUserID, DataTerminalName, userToken.BindingUser.Signature, userToken.BindingUser.Contacts, DataImage }); //Added by Donnie on 2016/04/27 //簽名各頭像變更不會影響在線狀態 if (DataTerminalName != "7" && DataTerminalName != "8") m_asyncSocketServer.UpdateUserState(curUserID, DataTerminalName); //state #endregion break; case "P": #region " 請求發送文件和同意接受文件 " //發起發送文件請求: 0019P接收人帳號(50b)發起人姓名(60b)S(50b)GMT時間(20b)文檔流的GUID(32b)訊息流水號(20b) //接收人同意請求: 0019P發起人帳號(50b)接收人姓名(60b)R(50b)GMT時間(20b)文檔流的GUID(32b)訊息流水號(20b) //包體: 文件名|大小|文件完整路徑 //接收方同意接收的請求等到接收方T通道建立完成再轉發給發送方 if (DataGroup != "R" && DataGroup.Length > 0) { switch (DataGroup) { case "Q": //斷開T通道的對象 //0019P發起人帳號(50b)S(60b)Q(50b)GMT時間(20b)文檔流的GUID(32b)訊息流水號(20b) //0019P接收人帳號(50b)R(60b)Q(50b)GMT時間(20b)文檔流的GUID(32b)訊息流水號(20b) if (DataTerminalName == "R") break; //不再主動斷開接收端(R)T通道連接,由客戶端自主斷開. string TID = DataGUID + "-" + DataTerminalName; //LogHelper.WriteLog("ThreadFunc", "準備斷開:" + TID + "的連接..."); SocketUserToken TSocket = m_asyncSocketServer.FileUserTokenList[TID] as SocketUserToken; if (TSocket != null) { //LogHelper.WriteLog("PcProcessor.ProcessCommand", "從S通道斷開:" + TID + "."); try { //主動關閉連接 //TSocket.Closing = true; m_asyncSocketServer.CloseClientSocket(TSocket); } catch { LogHelper.WriteLog("CloseClientSocket", "無法從S通道斷開:" + TID + ",可能已從T通道斷開."); } } else { LogHelper.WriteLog("PcProcessor.ProcessCommand", "沒有找到:" + TID + "."); } break; default: string MsgNO = base.ProcessTransferFileRequest(curUserID, DataType, DataTerminal, DataGroup, DataGUID, DataBody, DataTerminalName); // 向發送者發送回執7-03 base.PushFeedback(DataGUID, MsgNO); break; } } #endregion break; case "K": #region " 踢人7-06 " //0010K踢出目標帳號(50b)空格(60)空格(60)時間(20b)GUID(32b)訊息流水號(20b) //包體:P/M (P=PC端;M=移動端) //向被踢者發送回執7-06 SocketUserToken KickTarget = m_asyncSocketServer.PcUserTokenList[DataTerminal] as SocketUserToken; if (DataBody == "M") { KickTarget = m_asyncSocketServer.MobileUserTokenList[DataTerminal] as SocketUserToken; //if (KickTarget == null) //{ // KickTarget = _mobile_transmit_tb[DataTerminal] as UserSocket; //} } if (KickTarget != null) { Socket KickTargetSkt = KickTarget.ConnectSocket; bool ForceKickOut = DataGroup == "F"; //為F表示從服務器端強制斷開 try { //回執給PC端里,必須用DataGUID,因為PC端本地生成的GUID要和這個DataGUID匹配 List<byte[]> msgs = ParseProtocol.ConvertMsgToByte("06", "7", "", "", "", DataGUID, ""); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (KickTargetSkt) { if (KickTargetSkt.Connected) { foreach (byte[] msg in msgs) { //2016/05/19 test KickTarget.AsyncSendAgent.DoSendBuffer(msg); //KickTargetSkt.Send(msg); //base.SendData(KickTargetSkt, msg); } } } } catch (SocketException ex) { //客戶端異常,強踢 ForceKickOut = true; //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("PcProcessor.ProcessCommand", "發送消息回執時:" + (ex != null ? ex.Message : "")); } #region " 用戶在線就讓其自動登出,否則直接踢出 " //開踢 if (ForceKickOut) { //主動關閉連接 //KickTarget.Closing = true; m_asyncSocketServer.CloseClientSocket(KickTarget); } #endregion } else { //Kick FileTransferID KickTarget = m_asyncSocketServer.FileUserTokenList[DataTerminal] as SocketUserToken; if (KickTarget != null) { //主動關閉連接 //KickTarget.Closing = true; m_asyncSocketServer.CloseClientSocket(KickTarget); } } //通知管理員執行成功7-03 base.PushFeedback(DataGUID, ""); #endregion break; case "W": #region " 訂閱號消息 " if (DataGroup.Length > 0) { //用戶向訂閱號發命令 SendRequestToSubService(DataTerminal, DataGroup, DataBody, DataTerminalName, DataGUID, true); } #endregion break; case "X": #region " 請求和接受語音通話 " //發起請求: 0019X接收人帳號(50b)發起人姓名(60b)S(50b)GMT時間(20b)語音流的GUID(32b)訊息流水號(20b)空格(1b) //接受請求: 0019X發起人帳號(50b)接收人姓名(60b)R(50b)GMT時間(20b)語音流的GUID(32b)訊息流水號(20b)空格(1b) //包體: 內容暫時沒用 //接收方同意接收的請求等到接收方T通道建立完成再轉發給發送方 if (DataGroup.Length > 0) { switch (DataGroup) { case "R": //不做任何動作 break; case "A": //斷開T通道的對象 //0019X接收人帳號(50b)發起人姓名(60b)A(50b)GMT時間(20b)語音流的GUID(32b)訊息流水號(20b)空格(1b) //0019X發起人帳號(50b)接收人姓名(60b)A(50b)GMT時間(20b)語音流的GUID(32b)訊息流水號(20b)空格(1b) base.PushMessage("", ParseProtocol.ConvertMsgToByte(DataBody, DataType, curUserID, "AudioUser", DataGroup, DataGUID, "-1"), DataTerminal, m_asyncSocketServer.PcUserTokenList, "ProcessCommand-X"); break; default: base.ProcessAudioCallRequest(curUserID, DataType, DataTerminal, DataGroup, DataGUID, DataBody, DataTerminalName); break; } } #endregion break; case "Z": #region " 記錄登錄流量和耗時數據 " //DataBody包體格式: //類別A;流量(Byte);耗時(ms);開始(當地)日期(yyyy/MM/dd);開始(當地)時間(HH:mm:ss.fff);結束(當地)日期(yyyy/MM/dd);結束(當地)時間(HH:mm:ss.fff)|類別B;流量(Byte);耗時(ms);開始(當地)日期(yyyy/MM/dd);開始(當地)時間(HH:mm:ss.fff);結束(當地)日期(yyyy/MM/dd);結束(當地)時間(HH:mm:ss.fff) //邏輯: //根據帳號+IP抓到lrlxlog里此用戶最大UID作業log_uid base.SaveLoginStatData(userToken, DataTerminal, DataBody); #endregion break; } //System.Diagnostics.Debug.WriteLine("清除:" + receiveBuffer.DataCount.ToString() + "個Byte."); //把已處理的數據從緩存里清除 //receiveBuffer.Clear(receiveBuffer.DataCount); receiveBuffer.Clear(msgDataLength); //扣除已發完的包 base.m_readyPackage--; //發完一個包后,如果DataCount>0說明有粘包數據,嘗試發送出去,否則會影響後面數據的發送效率. //如果粘包不是一個完整的數據包就返回去接收數據 //while (receiveBuffer.DataCount > 0) //{ // try // { // ProcessCommand(userToken); // } // catch // { // // 繼續收 // return true; // } //} if (base.m_readyPackage > 0) return ProcessCommand(userToken); else return true; //System.Diagnostics.Debug.WriteLine("剩餘:" + receiveBuffer.DataCount.ToString() + "個Byte."); //test //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToLongTimeString() + " - " + DataType); //return true; } catch (Exception ex) { LogHelper.WriteLog("PcProcessor.ProcessCommand", string.Format("執行" + curDevice + "用戶:{0}命令時時出錯:{1}.", "@<" + userToken.BindingUser.ID + " " + userToken.ConnectSocket.RemoteEndPoint + "> ", (ex != null ? ex.Message : ""))); //主動關閉連接 //userToken.Closing = true; return false; } }
/// <summary> /// 線程執行體,轉發消息(PC端) /// </summary> /// <param name="obj">傳遞給線程執行體的用戶名,用以與用戶通信</param> private void ThreadFunc(object obj) { if (obj == null) return; // 通過轉發表得到當前用戶套接字 //Socket clientSkt = _transmit_tb[obj] as Socket; UserSocket User = _transmit_tb[obj] as UserSocket; if (User != null) { Socket clientSkt = User.Socket; while (true) { try { //返回解包后的資料(返回數組 0=type ; 1=終端; 2=群號; 3=時間; 4=消息ID; 5=消息內容; 6=終端姓名) object[] ReceiveData = ConvertMethod.UnMsgPackage(clientSkt); string DataType = ReceiveData[0].ToString(); //如果數據類別為空就踢出 if (DataType == "") { LogHelper.WriteLog("ThreadFunc", "讀取用戶:" + obj.ToString() + "數據時連接異常斷開."); //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):catch (SocketException)", "讀取用戶:" + obj.ToString() + "的數據時發生異常,斷開連接."); //接收數據時發生異常,被置空.從哈希表中移除 try { try { if (clientSkt.Connected) { clientSkt.Shutdown(SocketShutdown.Both); //clientSkt.Disconnect(false); } clientSkt.Close(); #region " 聯絡人狀態變更 " //通知在線的聯絡人當前用戶改變了狀態 //User.SetUserState("6"); //UpdateUserLog(User.ID, "1", "0", "PC端異常登出"); //如果手機端沒在線就通知聯絡人我離線了 ProcessPCUserState(User); #endregion } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.System, "CloseClientSocket", "嘗試關閉一個異常的Socket連接時出現問題:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "嘗試關閉一個異常的Socket連接時出現問題:" + (ex != null ? ex.Message : "")); } lock (_transmit_tb.SyncRoot) _transmit_tb.Remove(obj); //線程池不會被遍歷,不鎖. _thread_tb.Remove(obj); } catch { } Thread.CurrentThread.Abort(); break; //如果執行到這里就跳出(一般到上一句就結束了) } string DataTerminal = ReceiveData[1].ToString(); string DataGroup = ReceiveData[2].ToString(); string DataGUID = ReceiveData[4].ToString(); string DataBody = (DataType != "I" ? ReceiveData[5].ToString() : "N/A"); // 非屏幕截圖時才有值 byte[] DataImage = (DataType == "I" ? (byte[])ReceiveData[5] : null); // 屏幕截圖時才有值 string DataTerminalName = ReceiveData[6].ToString(); //byte[] headerPacketBuff = new byte[_headerPacket]; ////接收包頭 //clientSkt.Receive(headerPacketBuff); //string headerData = Encoding.UTF8.GetString(headerPacketBuff).TrimEnd('\0'); //int DataLen = ConvertMethod.Convert16To10(headerData.Substring(0, 4)); // 包體長度(16進制轉10進制) //string DataType = headerData.Substring(4, 1); // 包類別 //string DataTerminal = headerData.Substring(5, 50).Replace(" ", ""); // 包終端 ////接收包體 //byte[] bodyPacketBuff = new byte[DataLen]; //clientSkt.Receive(bodyPacketBuff); //string bodyData = Encoding.UTF8.GetString(bodyPacketBuff).TrimEnd('\0'); ////接收包尾 //byte[] tailPacketBuff = new byte[1]; //clientSkt.Receive(tailPacketBuff); //string tailData = Encoding.UTF8.GetString(tailPacketBuff).TrimEnd('\0'); // 分類處理 switch (DataType) { case "1": #region " 用戶離線 " try { //通知在線的聯絡人當前用戶離線了 //User.State = UserSocket.UserStates.Offline; //UpdateUserLog(User.ID, "1", "0", "PC端登出"); //如果手機端沒在線就通知聯絡人我離線了 //DataGroup = ""; //TEST if (DataGroup.ToUpper() != "APP") { //普通用戶記錄 ProcessPCUserState(User); LogHelper.WriteLog("ThreadFunc", "用戶:" + obj.ToString() + "離線."); } if (clientSkt.Connected) { clientSkt.Shutdown(SocketShutdown.Both); //clientSkt.Disconnect(false); } clientSkt.Close(); //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):catch (SocketException)", "用戶:" + obj.ToString() + "通知離線."); } catch (SocketException ex) { if (DataGroup.ToUpper() != "APP") { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):catch (SocketException)", "用戶:" + obj.ToString() + "離線時發生錯誤:" + (ex != null ? ex.Message : "")); LogHelper.WriteLog("ThreadFunc", "用戶:" + obj.ToString() + "離線時發生錯誤:" + (ex != null ? ex.Message : "")); } } //UserSocket WebUser = _ws_transmit_tb[User.ID] as UserSocket; //if (WebUser == null) //{ // SendUserState(User); // UpdateUserState(User.ID, "6"); //離線 //} try { lock (_transmit_tb.SyncRoot) _transmit_tb.Remove(obj); //線程池不會被遍歷,不鎖. _thread_tb.Remove(obj); } catch (Exception ex1) { LogHelper.WriteLog("ThreadFunc", "從HashTable中移除用戶:" + obj.ToString() + "時發生錯誤:" + (ex1 != null ? ex1.Message : "")); } Thread.CurrentThread.Abort(); #endregion break; case "5": #region " 群(異動)系統訊息 " SendGroupSysMessage("P", clientSkt, obj.ToString(), DataGroup, DataGUID, DataBody); #endregion break; case "6": #region " 心跳包 " if (_transmit_tb.ContainsKey(DataTerminal)) { // 直接把訊息還給發送者 //Socket receiverSkt = _transmit_tb[DataTerminal] as Socket; UserSocket recUser = _transmit_tb[DataTerminal] as UserSocket; try { Socket receiverSkt = recUser.Socket; List<byte[]> msgs = ConvertMethod.ConvertMsgToByte(DataBody, DataType, "", "", "", DataGUID); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 if (receiverSkt.Connected) { lock (receiverSkt) { foreach (byte[] msg in msgs) { receiverSkt.Send(msg); //SendData(receiverSkt, msg); } } } else { //用戶已經斷開了 LogHelper.WriteLog("ThreadFunc", "向用戶:" + DataTerminal + "轉發心跳包時發現用戶斷開連接了"); } //clsClientLog.WriteLog(clsClientLog.LogType.Info, "ThreadFunc(object obj):default", "成功向: " + _receiver + " 發送信息: " + _packetBuff); } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "轉發心跳包時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "向用戶:" + DataTerminal + "轉發心跳包時發生錯誤:" + (ex != null ? ex.Message : "")); } } #endregion break; case "7": #region " 控制臺消息(7-07/7-08) " ProcessConsoleCommands(DataBody); #endregion break; case "8": #region " 發送在線用戶ID清單 " try { DataBody = ""; switch (DataGroup) { case "P": //PC lock (_transmit_tb.SyncRoot) { foreach (DictionaryEntry de in _transmit_tb) { DataBody += de.Key.ToString() + ","; } } break; case "M": //Web + 手機 lock (_ws_transmit_tb.SyncRoot) { foreach (DictionaryEntry de in _ws_transmit_tb) { DataBody += de.Key.ToString() + ","; } } lock (_mobile_transmit_tb.SyncRoot) { foreach (DictionaryEntry de in _mobile_transmit_tb) { DataBody += de.Key.ToString() + ","; } } break; case "A": //APP lock (_app_transmit_tb.SyncRoot) { foreach (DictionaryEntry de in _app_transmit_tb) { DataBody += de.Key.ToString() + ","; } } break; case "F": //File lock (_file_transmit_tb.SyncRoot) { foreach (DictionaryEntry de in _file_transmit_tb) { DataBody += de.Key.ToString() + ","; } } break; default: DataBody = "無效列表類別."; break; } // 去掉最後一個逗號 if (DataBody.Length > 0) { DataBody = DataBody.Substring(0, DataBody.Length - 1); } else { DataBody = "無"; } List<byte[]> msgs = ConvertMethod.ConvertMsgToByte(DataBody, DataType, DataTerminal, DataTerminalName, "", DataGUID); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (clientSkt) { foreach (byte[] msg in msgs) { clientSkt.Send(msg); //SendData(clientSkt, msg); } } //clsClientLog.WriteLog(clsClientLog.LogType.Info, "ThreadFunc(object obj):default", "成功向: " + _receiver + " 發送信息: " + _packetBuff); } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送在線用戶ID清單時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送在線用戶ID清單時:" + (ex != null ? ex.Message : "")); } #endregion break; case "H": #region " 發送服務器健康報告 " try { //[#1]:120 [PC端用戶] //[#2]:12 [移動端用戶] //[#3]:10 [登錄隊列] //[#4]:12/50 [空閒登錄線程] //[#5]:10 [APP用戶] //[#6]:2 [文件傳送用戶] //[#7]:0 [歷史消息標記已讀隊列] //[#8]:89 [用戶狀態推送隊列] //[#9]:0/10 [空間狀態推送線程] //[#10]:10 [設備數據更新隊列] DataBody = ""; //[PC端用戶] DataBody += "[#1]:" + _transmit_tb.Count.ToString() + "|"; //[移動端用戶] DataBody += "[#2]:" + (_ws_transmit_tb.Count + _mobile_transmit_tb.Count).ToString() + "|"; //[登錄隊列] DataBody += "[#3]:" + UsersQueue.Count.ToString() + "|"; //[空閒登錄線程] DataBody += "[#4]:" + LoginThreadsQueue.Count.ToString() + "/" + MaxLoginThreads.ToString() + "|"; //[APP用戶] DataBody += "[#5]:" + _app_transmit_tb.Count.ToString() + "|"; //[文件傳送用戶] DataBody += "[#6]:" + _file_transmit_tb.Count.ToString() + "|"; //[歷史消息標記已讀隊列] DataBody += "[#7]:" + MarkReadHistoryMsgQueue.Count.ToString() + "|"; //[用戶狀態推送隊列] DataBody += "[#8]:" + StateNotifyQueue.Count.ToString() + "|"; //[空間狀態推送線程] DataBody += "[#9]:" + StateNofityThreadsQueue.Count.ToString() + "/" + MaxStateNotifyThreads.ToString() + "|"; //[設備數據更新隊列] DataBody += "[#10]:" + VDataQueue.Count.ToString(); List<byte[]> msgs = ConvertMethod.ConvertMsgToByte(DataBody, DataType, DataTerminal, DataTerminalName, "", DataGUID); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (clientSkt) { foreach (byte[] msg in msgs) { clientSkt.Send(msg); //SendData(clientSkt, msg); } } //clsClientLog.WriteLog(clsClientLog.LogType.Info, "ThreadFunc(object obj):default", "成功向: " + _receiver + " 發送信息: " + _packetBuff); } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送在線用戶ID清單時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送服務器健康報告時時:" + (ex != null ? ex.Message : "")); } #endregion break; case "C": #region " 群命令 " // 抓出群成員 using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 //DateTime MsgDT = DateTime.Now; string MsgNO = this.InsertCmd(conn, obj.ToString(), DataBody, DataGroup, DataGUID); if (MsgNO.Length > 0) { // 向管理員發的命令不轉發 if (DataGroup.Length > 0) { //系統將命令轉發給群成員(以發送者的帳號) SendGroupCommand(obj.ToString(), DataGroup, DataBody, DataTerminalName, conn, DataGUID, MsgNO); } // 轉發完再發回執 // 向發送者發送回執7-03 try { //回執給PC端里,必須用DataGUID,因為PC端本地生成的GUID要和這個DataGUID匹配 List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("03", "7", "", "", "", DataGUID, MsgNO); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (clientSkt) { foreach (byte[] msg in msgs) { clientSkt.Send(msg); //SendData(clientSkt, msg); } } } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送命令回執時:" + (ex != null ? ex.Message : "")); } } conn.CloseConnection(); } catch { conn.CloseConnection(); } } #endregion break; case "D": #region " 撤回消息 " //0001D發送人帳號(50b)接收對象類別(U=人;G=群)(60b)接收人/接收群(50b)GMT時間(20b)要撤回消息的GUID(32b)訊息流水號(20b) using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中(1=撤回,M=消息lrmsg) string MsgNO = this.InsertSysMsg(conn, obj.ToString(), DataBody, "1", "M", (DataTerminalName == "G" ? DataGroup : ""), (DataTerminalName == "U" ? DataGroup : ""), DataGUID); if (MsgNO.Length > 0) { //系統將訊息轉發給群成員(以發送者的帳號) SendGroupSysBroadcast("P", "D", "1", "M", DataTerminal, DataGroup, DataBody, DataTerminalName, conn, DataGUID, MsgNO); // 轉發完再發回執 // 向發送者發送回執7-03 try { //回執給PC端里,必須用DataGUID,因為PC端本地生成的GUID要和這個DataGUID匹配 List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("03", "7", "1", "M", "", DataGUID, MsgNO); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (clientSkt) { foreach (byte[] msg in msgs) { clientSkt.Send(msg); //SendData(clientSkt, msg); } } } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送消息回執時:" + (ex != null ? ex.Message : "")); } } conn.CloseConnection(); } catch { conn.CloseConnection(); } } #endregion break; case "G": #region " 群組訊息 " // 抓出群成員 using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 //DateTime MsgDT = DateTime.Now; string MsgNO = this.InsertMsg(conn, obj.ToString(), DataBody, DataGroup, "", "1", DataGUID, false); if (MsgNO.Length > 0) { //系統將訊息轉發給群成員(以發送者的帳號) SendGroupBroadcast("P", obj.ToString(), DataGroup, DataBody, DataTerminalName, conn, DataGUID, MsgNO); // 轉發完再發回執 // 向發送者發送回執7-03 try { //回執給PC端里,必須用DataGUID,因為PC端本地生成的GUID要和這個DataGUID匹配 List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("03", "7", "", "", "", DataGUID, MsgNO); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (clientSkt) { foreach (byte[] msg in msgs) { clientSkt.Send(msg); //SendData(clientSkt, msg); } } } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送消息回執時:" + (ex != null ? ex.Message : "")); } } conn.CloseConnection(); } catch { conn.CloseConnection(); } } #endregion break; case "I": #region " 轉發屏幕截圖 " //DataTerminal是接收人帳號 //DataTerminalName是發送人姓名 using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 string MsgNO = this.InsertImage(conn, obj.ToString(), DataImage, DataGroup, DataTerminal, "1", DataGUID); if (MsgNO.Length > 0) { //沒改完,要用特殊方式打包 //開始發送 if (DataGroup.Length == 0) { //向人發 SendP2PImage("P", obj.ToString(), DataTerminalName, DataTerminal, DataImage, conn, DataGUID, MsgNO); } else { //向群發 SendGroupImage("P", obj.ToString(), DataGroup, DataImage, DataTerminalName, conn, DataGUID, MsgNO); } // 轉發完再發回執 // 向發送者發送回執7-03 try { //回執給PC端里,必須用DataGUID,因為PC端本地生成的GUID要和這個DataGUID匹配 List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("03", "7", "", "", "", DataGUID, MsgNO); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (clientSkt) { foreach (byte[] msg in msgs) { clientSkt.Send(msg); //SendData(clientSkt, msg); } } } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送消息回執時:" + (ex != null ? ex.Message : "")); } } conn.CloseConnection(); } catch { conn.CloseConnection(); } } #endregion break; case "U": //人對人信息 case "T": //測試工具使用 #region " 用戶訊息 " //別搞暈了 //DataTerminal是接收人帳號 //DataTerminalName是發送人姓名 using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 //DateTime MsgDT = DateTime.Now; //T=測試用(超哥神器) string MsgNO = this.InsertMsg(conn, obj.ToString(), DataBody, "", DataTerminal, "1", DataGUID, DataType == "T"); if (MsgNO.Length > 0) { //開始發送 SendP2PMessage("P", obj.ToString(), DataTerminalName, DataTerminal, DataBody, conn, DataGUID, MsgNO, DataType); // 轉發完再發回執 // 向發送者發送回執7-03 try { //回執給PC端里,必須用DataGUID,因為PC端本地生成的GUID要和這個DataGUID匹配 List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("03", "7", "", "", "", DataGUID, MsgNO); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (clientSkt) { foreach (byte[] msg in msgs) { clientSkt.Send(msg); //SendData(clientSkt, msg); } } } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送消息回執時:" + (ex != null ? ex.Message : "")); } } conn.CloseConnection(); } catch { conn.CloseConnection(); } } #endregion break; case "S": #region " 聯絡人狀態變更 " //通知在線的聯絡人當前用戶改變了狀態 //0=空閒|1=上線|2=離開|3=忙碌|4=不要打擾|5=隱身|6=離線|7=簽名|8=換頭像 User.SetUserState(DataTerminalName); //特殊處理簽名操作 if (DataTerminalName == "7") { //User.ChangeSignature = true; User.Signature = DataBody; //signature UpdateUserLog(User.ID, "2", "0", User.Signature); } else if (DataTerminalName == "8") { // 變更頭像的處理(未完成) } StateNotifyQueue.Enqueue(new List<object>() { User, DataTerminalName }); //SendUserState(User); //改為獨立線程來發 //如果此聯絡人在線就通知他(她)當前用戶上線了 //try //{ // Thread stateThread = new Thread(new ParameterizedThreadStart(StateNotifyThreadFunc)); // stateThread.Start(User); //} //catch //{ } //User.ChangeSignature = false; //復位 if (DataTerminalName != "7") UpdateUserState(User.ID, DataTerminalName); //state #endregion break; case "P": #region " 請求發送文件和同意接受文件 " //發起發送文件請求: 0019P接收人帳號(50b)發起人姓名(60b)S(50b)GMT時間(20b)文檔流的GUID(32b)訊息流水號(20b) //接收人同意請求: 0019P發起人帳號(50b)接收人姓名(60b)R(50b)GMT時間(20b)文檔流的GUID(32b)訊息流水號(20b) //包體: 文件名|大小|文件完整路徑 //接收方同意接收的請求等到接收方T通道建立完成再轉發給發送方 if (DataGroup != "R" && DataGroup.Length > 0) { switch (DataGroup) { case "Q": //斷開T通道的對象 //0019P發起人帳號(50b)S(60b)Q(50b)GMT時間(20b)文檔流的GUID(32b)訊息流水號(20b) //0019P接收人帳號(50b)R(60b)Q(50b)GMT時間(20b)文檔流的GUID(32b)訊息流水號(20b) string TID = DataGUID + "-" + DataTerminalName; //LogHelper.WriteLog("ThreadFunc", "準備斷開:" + TID + "的連接..."); UserSocket TSocket = _file_transmit_tb[TID] as UserSocket; if (TSocket != null) { try { if (TSocket.Socket != null) { if (TSocket.Socket.Connected) { TSocket.Socket.Shutdown(SocketShutdown.Both); //clientSkt.Disconnect(false); } TSocket.Socket.Close(); //LogHelper.WriteLog("ThreadFunc", "成功斷開:" + TID + "的連接."); } } catch (Exception ex) { //LogHelper.WriteLog("ThreadFunc", "嘗試斷開:" + TID + "的連接時發生錯誤." + (ex != null ? ex.Message : "")); } //線程池不會被遍歷,不鎖. _file_transmit_tb.Remove(TID); //線程池不會被遍歷,不鎖. _file_thread_tb.Remove(TID); } else { LogHelper.WriteLog("ThreadFunc", "沒有找到:" + TID + "."); } break; default: string MsgNO = ProcessTransferFileRequest("P", obj.ToString(), DataType, DataTerminal, DataGroup, DataGUID, DataBody, DataTerminalName); // 向發送者發送回執7-03 try { //回執給PC端里,必須用DataGUID,因為PC端本地生成的GUID要和這個DataGUID匹配 List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("03", "7", "", "", "", DataGUID, MsgNO); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (clientSkt) { foreach (byte[] msg in msgs) { clientSkt.Send(msg); //SendData(clientSkt, msg); } } } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送消息回執時:" + (ex != null ? ex.Message : "")); } break; } } #endregion break; case "K": #region " 踢人7-06 " //0010K踢出目標帳號(50b)空格(60)空格(60)時間(20b)GUID(32b)訊息流水號(20b) //包體:P/M (P=PC端;M=移動端) //向被踢者發送回執7-06 UserSocket KickTarget = _transmit_tb[DataTerminal] as UserSocket; if (DataBody == "M") { KickTarget = _ws_transmit_tb[DataTerminal] as UserSocket; if (KickTarget == null) { KickTarget = _mobile_transmit_tb[DataTerminal] as UserSocket; } } if (KickTarget != null) { Socket KickTargetSkt = KickTarget.Socket; bool ForceKickOut = false; try { //回執給PC端里,必須用DataGUID,因為PC端本地生成的GUID要和這個DataGUID匹配 List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("06", "7", "", "", "", DataGUID, ""); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (KickTargetSkt) { if (KickTargetSkt.Connected) { foreach (byte[] msg in msgs) { KickTargetSkt.Send(msg); //SendData(KickTargetSkt, msg); } } } } catch (SocketException ex) { //客戶端異常,強踢 ForceKickOut = true; //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送消息回執時:" + (ex != null ? ex.Message : "")); } #region " 用戶在線就讓其自動登出,否則直接踢出 " //開踢 if (ForceKickOut) { try { if (KickTargetSkt.Connected) { KickTargetSkt.Shutdown(SocketShutdown.Both); //userSkt.Disconnect(false); } KickTargetSkt.Close(); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "踢出用戶:" + DataTerminal + "時出錯:" + (ex != null ? ex.Message : "")); } #region " 聯絡人狀態變更 " ProcessPCUserState(KickTarget); #endregion try { lock (_transmit_tb.SyncRoot) _transmit_tb.Remove(DataTerminal); Thread kickTargetThread = _thread_tb[DataTerminal] as Thread; if (kickTargetThread != null) { kickTargetThread.Abort(); _thread_tb.Remove(DataTerminal); } } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "結束被踢出用戶:" + DataTerminal + "線程時出錯:" + (ex != null ? ex.Message : "")); } } #endregion } else { //Kick FileTransferID KickTarget = _file_transmit_tb[DataTerminal] as UserSocket; if (KickTarget != null) { Socket KickTargetSkt = KickTarget.Socket; try { if (KickTargetSkt.Connected) { KickTargetSkt.Shutdown(SocketShutdown.Both); //userSkt.Disconnect(false); } KickTargetSkt.Close(); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "踢出用戶:" + DataTerminal + "時出錯:" + (ex != null ? ex.Message : "")); } try { lock (_file_transmit_tb.SyncRoot) _file_transmit_tb.Remove(DataTerminal); Thread kickTargetThread = _file_thread_tb[DataTerminal] as Thread; if (kickTargetThread != null) { kickTargetThread.Abort(); _file_thread_tb.Remove(DataTerminal); } } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "結束被踢出用戶:" + DataTerminal + "線程時出錯:" + (ex != null ? ex.Message : "")); } } } try { //通知管理員執行成功7-03 List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("03", "7", "", "", "", DataGUID, ""); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (clientSkt) { if (clientSkt.Connected) { foreach (byte[] msg in msgs) { clientSkt.Send(msg); //SendData(clientSkt, msg); } } } } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("ThreadFunc", "發送消息回執時:" + (ex != null ? ex.Message : "")); } #endregion break; } } catch (SocketException) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):catch (SocketException)", "用戶:" + obj.ToString() + "異常斷開連接."); try { LogHelper.WriteLog("ThreadFunc", "用戶:" + obj.ToString() + "異常斷開連接."); if (clientSkt.Connected) { clientSkt.Shutdown(SocketShutdown.Both); //clientSkt.Disconnect(false); } clientSkt.Close(); #region " 聯絡人狀態變更 " //通知在線的聯絡人當前用戶改變了狀態 //User.SetUserState("6"); //UpdateUserLog(User.ID, "1", "0", "PC端異常登出"); //如果手機端沒在線就通知聯絡人我離線了 ProcessPCUserState(User); //UserSocket WebUser = _ws_transmit_tb[User.ID] as UserSocket; //if (WebUser == null) //{ // SendUserState(User); // UpdateUserState(User.ID, "6"); //離線 //} #endregion lock (_transmit_tb.SyncRoot) _transmit_tb.Remove(obj); //線程池不會被遍歷,不鎖. _thread_tb.Remove(obj); } catch { } Thread.CurrentThread.Abort(); } } } }
protected void SendVoice(string DataTerminal, string DataGroup, byte[] DataVoice, string DataTerminalName, string DataGUID, string VoiceSeconds) { //處理邏輯: 將lrtdmsg.msg_img留空. 再將完整音頻數據放到對照表lrmsgimg里. // 用戶點擊錄音圖標再下載完整音頻數據 // try { string curUserID = m_userToken.BindingUser.ID; //DataTerminal是接收人帳號 //DataTerminalName是發送人姓名 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 string MsgNO = InsertVoice(conn, curUserID, DataVoice, DataGroup, DataTerminal, "1", DataGUID, VoiceSeconds); if (MsgNO.Length > 0) { //沒改完,要用特殊方式打包 //開始發送 if (DataGroup.Length == 0) { //向人發 SendP2PVoice(curUserID, DataTerminalName, DataTerminal, conn, DataGUID, MsgNO, VoiceSeconds); } else { //向群發 SendGroupVoice(DataTerminal, DataGroup, DataTerminalName, conn, DataGUID, MsgNO, VoiceSeconds); } // 轉發完再發回執 // 向發送者發送回執7-03 PushFeedback(DataGUID, MsgNO); } conn.CloseConnection(); } catch { conn.CloseConnection(); } } } catch (Exception ex) { LogHelper.WriteLog("SendVoice", ex.Message); } }
/// <summary> /// 系統公告消息 /// </summary> /// <param name="Command"></param> /// <param name="Seq"></param> /// <param name="Region"></param> /// <param name="MsgText"></param> protected void SendSysNotice(string Command, string Seq, string Region, string MsgText) { #region " 更新公告內容和區域 " lock (m_asyncSocketServer.SysNotices.SyncRoot) { if (m_asyncSocketServer.SysNotices.ContainsKey(Region)) { //ALL 也會存里面 List<NoticeMsg> nMsgs = (List<NoticeMsg>)m_asyncSocketServer.SysNotices[Region]; NoticeMsg nMsg = nMsgs.Find(delegate(NoticeMsg _msg) { return _msg.MsgSeq == Seq; }); if (nMsg != null) { if (Command == "1") { // 替換現有的公告 nMsg.MsgText = MsgText; } else { // 移除現有的公告 nMsgs.Remove(nMsg); if (nMsgs.Count == 0) { // 當前區域沒有公告了,將區域移除 m_asyncSocketServer.SysNotices.Remove(Region); } } } else { if (Command == "1") { // 新公告 nMsgs.Add(new NoticeMsg() { MsgSeq = Seq, MsgText = MsgText }); } } } else { if (Command == "1") { //新公告 m_asyncSocketServer.SysNotices.Add(Region, new List<NoticeMsg>() { new NoticeMsg() { MsgSeq = Seq, MsgText = MsgText } }); } } } #endregion // 抓出群成員 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { #region " 更新廣播內容到數據庫 " if (conn.OpenDataTable("select uid from lrbroadcast (nolock) where region_id = '" + Region + "' and bdc_seq = '" + Seq + "'", CommandType.Text).Rows.Count > 0) { //有資料 conn.ExecuteSQL("update a set a.bdc_cmd='" + Command + "',a.bdc_text=N'" + MsgText + "' from lrbroadcast a where a.region_id = '" + Region + "' and a.bdc_seq = '" + Seq + "'"); } else { //沒資料 if (Command == "1") { conn.ExecuteSQL("insert into lrbroadcast (region_id,bdc_seq,bdc_text,bdc_cmd) values('" + Region + "','" + Seq + "',N'" + MsgText + "','" + Command + "')"); } } #endregion string strWhere = "where ie_cancel <> 'Y' and user_state <> '6'"; if (Region.ToUpper() == "ALL") { strWhere += " and user_region > ''"; } else { strWhere += " and user_region = '" + Region + "'"; } DataTable UserList = conn.OpenDataTable("select user_no from lrtduser (nolock) " + strWhere, CommandType.Text); //儘早釋放SQL資源 conn.CloseConnection(); if (UserList.Rows.Count > 0) { // 提前打包好,沒必要放到for循環里去做 List<byte[]> msgs = ParseProtocol.ConvertMsgToByte(MsgText, "B", Command, Seq, Region, "", ""); foreach (DataRow User in UserList.Rows) { //有沒有必要PC和MOBLIE端各開個一個欄位來存放消息是否讀取的標記? #region " PC Client " PushMessage("", msgs, User["user_no"].ToString(), m_asyncSocketServer.PcUserTokenList, "SendSysNotice"); #endregion #region " Mobile Client " //Users = PushMessage(Users, msgs, User["msg_to"].ToString(), m_asyncSocketServer.MobileUserTokenList, "SendGroupSysMessage"); #endregion } } UserList.Dispose(); UserList = null; #region " 向發送者發送回執7-03 " PushFeedback("", ""); #endregion } catch { conn.CloseConnection(); } } }
private void GetSysData() { //1.活動用戶(14天內有發消息的) //2.在線用戶 //3.註冊用戶 //4.今天消息量 //5.累積消息量 string ActiveDate = DateTime.Now.AddDays(-14).ToString("yyyy/MM/dd"); // 兩周內 string SQL = ""; //抓數據 using (SQLHelper conn = new SQLHelper(DBInfo)) { try { conn.OpenConnection(); //1.活動用戶(14天內有發消息的) SQL = "select COUNT(1) as active_users_count from " + "\r\n" + "( " + "\r\n" + " select a.msg_from from lrtdmsg a (nolock) join lrtduser b (nolock) on a.msg_from=b.user_no where a.msg_date>='" + ActiveDate + "' group by a.msg_from " + "\r\n" + ") a"; ActiveUsersCount = conn.OpenDataTable(SQL, CommandType.Text).Rows[0]["active_users_count"].ToString(); //2.在線用戶(App客戶端不算) OnlineUsersCount = ((PcUserTokenList != null ? PcUserTokenList.Count : 0) + (MobileUserTokenList != null ? MobileUserTokenList.Count : 0)).ToString(); //3.註冊用戶 SQL = "select COUNT(1) as registered_users_count from lrtduser (nolock)"; RegisteredUsersCount = conn.OpenDataTable(SQL, CommandType.Text).Rows[0]["registered_users_count"].ToString(); //4.今天消息量 SQL = "select COUNT(1) as today_msgs_count from lrtdmsg (nolock) where msg_date='" + DateTime.Now.ToString("yyyy/MM/dd") + "' and msg_from in (select user_no from lrtduser (nolock))"; TodayMessagesCount = conn.OpenDataTable(SQL, CommandType.Text).Rows[0]["today_msgs_count"].ToString(); //5.累積消息量 SQL = "select COUNT(1) as total_msgs_count from lrtdmsg (nolock) where msg_from in (select user_no from lrtduser (nolock))"; TotalMessagesCount = conn.OpenDataTable(SQL, CommandType.Text).Rows[0]["total_msgs_count"].ToString(); conn.CloseConnection(); } catch (Exception ex) { conn.CloseConnection(); //clsClientLog.WriteLog(clsClientLog.LogType.Error, "SysTreadFunc", "讀取平臺數據時:" + (ex != null ? ex.Message : "")); LogHelper.WriteLog("SysTreadFunc()", "讀取平臺數據時:" + (ex != null ? ex.Message : "")); return; } } }
/// <summary> /// 保存登錄流量和耗時數據 /// </summary> /// <param name="userToken"></param> /// <param name="DataTerminal"></param> /// <param name="DataBody"></param> protected void SaveLoginStatData(SocketUserToken userToken, string DataTerminal, string DataBody) { //DataBody包體格式: //類別A;流量(Byte);耗時(ms);開始(當地)日期(yyyy/MM/dd);開始(當地)時間(HH:mm:ss.fff);結束(當地)日期(yyyy/MM/dd);結束(當地)時間(HH:mm:ss.fff)|類別B;流量(Byte);耗時(ms);開始(當地)日期(yyyy/MM/dd);開始(當地)時間(HH:mm:ss.fff);結束(當地)日期(yyyy/MM/dd);結束(當地)時間(HH:mm:ss.fff) //邏輯: //根據帳號+IP抓到lrlxlog里此用戶最大UID作業log_uid string[] StatData = DataBody.Split('|'); if (StatData.Length > 0) { DateTime curDate = DateTime.Now; string Today = curDate.ToString("yyyy/MM/dd"); string Yesterday = curDate.AddDays(-1).ToString("yyyy/MM/dd"); //防止登錄時剛好跨天 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { conn._Transaction = conn._Connection.BeginTransaction(); DataTable recTmp = conn.OpenDataTable("select MAX(uid) as log_uid from lrlxlog (nolock) " + "\r\n" + "where log_date between '" + Yesterday + "' and '" + Today + "' and user_no='" + DataTerminal + "' and log_ip='" + ((IPEndPoint)userToken.ConnectSocket.RemoteEndPoint).Address.ToString() + "'", CommandType.Text); if (recTmp.Rows.Count > 0) { long log_uid = long.Parse(recTmp.Rows[0]["log_uid"].ToString()); string[] statValues; foreach (string stat in StatData) { statValues = stat.Split(';'); //[0]:類別 //[1]:流量(Byte) //[2]:耗時(ms) //[3]:開始(當地)日期(yyyy/MM/dd) //[4]:開始(當地)時間(HH:mm:ss.fff) //[5]:結束(當地)日期(yyyy/MM/dd) //[6]:結束(當地)時間(HH:mm:ss.fff) if (statValues.Length == 7) { conn.ExecuteSQL("insert into lrlxstat (log_uid,stat_type,data_size,duration_time,stat_sdate,stat_stime,stat_edate,stat_etime,ie_ymd,ie_time,ie_user)" + "\r\n" + "values(" + log_uid + ",'" + statValues[0] + "'," + statValues[1] + "," + statValues[2] + ",'" + statValues[3] + "','" + statValues[4] + "','" + statValues[5] + "','" + statValues[6] + "','" + curDate.ToString("yyyy/MM/dd") + "','" + curDate.ToString("HH:mm:ss") + "','" + DataTerminal + "')"); } } } conn._Transaction.Commit(); conn.CloseConnection(); } catch { conn._Transaction.Rollback(); conn.CloseConnection(); } } } }
/// <summary> /// 處理當前用戶離線狀態的通知 /// </summary> /// <param name="userToken"></param> private void ProcessUserOfflineState(SocketUserToken userToken) { if (userToken == null || userToken.BindingUser == null) return; User curUser = userToken.BindingUser; try { //判斷用戶有沒登錄成功,有就通知聯絡人用戶狀態變更q if (m_pcUserTokenList.ContainsKey(curUser.ID)) { //目前只寫對PC端用戶,應該還要考慮其他用戶 //通知在線的聯絡人當前用戶改變了狀態 curUser.SetUserState("6"); using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { DoUpdateUserLog(conn, curUser.ID, "1", ((int)curUser.Mobile).ToString(), "客戶端登出", ((IPEndPoint)userToken.ConnectSocket.RemoteEndPoint).Address.ToString(), "", "", null); //如果手機端沒在線就通知聯絡人此人離線了 SocketUserToken MobileUser = m_mobileUserTokenList[curUser.ID] as SocketUserToken; if (MobileUser == null) { //StateNotifyQueue.Enqueue(new List<object>() { userToken, ((int)curUser.State).ToString() }); //ID,狀態,簽名,聯絡人清單,頭像數據 if (curUser.Contacts.Count > 0) StateNotifyQueue.Enqueue(new List<object>() { curUser.ID, ((int)curUser.State).ToString(), curUser.Signature, curUser.Contacts, null }); DoUpdateUserState(conn, curUser.ID, "6"); //離線 } conn.CloseConnection(); } catch { conn.CloseConnection(); } } } } catch (Exception ex) { LogHelper.WriteLog("ProcessUserOfflineState", "通知聯絡人用戶:" + curUser.ID + "離線時出錯:" + (ex != null ? ex.Message : "")); } ////通知在線的聯絡人當前用戶改變了狀態 //curUser.SetUserState("6"); //using (SQLHelper conn = new SQLHelper(DBInfo)) //{ // conn.OpenConnection(); // try // { // DoUpdateUserLog(conn, curUser.ID, "1", "0", "PC端登出"); // //如果手機端沒在線就通知聯絡人此人離線了 // UserSocket WebUser = _ws_transmit_tb[curUser.ID] as UserSocket; // if (WebUser == null) // { // WebUser = _mobile_transmit_tb[curUser.ID] as UserSocket; // if (WebUser == null) // { // StateNotifyQueue.Enqueue(new List<object>() { curUser, ((int)curUser.State).ToString() }); // DoUpdateUserState(conn, curUser.ID, "6"); //離線 // } // } // conn.CloseConnection(); // } // catch // { // conn.CloseConnection(); // } //} }
/// <summary> /// 轉發群消息 /// </summary> /// <param name="DataTerminal"></param> /// <param name="DataGroup"></param> /// <param name="DataGUID"></param> /// <param name="DataBody"></param> /// <param name="DataTerminalName"></param> /// <param name="conn"></param> /// <param name="MsgNO"></param> protected void SendGroupBroadcast(string DataTerminal, string DataGroup, string DataBody, string DataTerminalName, string MsgGUID, bool IsPushMode) { // 抓出群成員 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 // DataType == "L"時, DataTerminalName為Pull消息子分類(表名) string MsgNO = this.InsertMsg(conn, DataTerminal, DataBody, DataGroup, "", "1", (IsPushMode ? "" : DataTerminalName), MsgGUID, false, IsPushMode); if (MsgNO.Length > 0) { // 系統將訊息轉發給群成員(以發送者的帳號) //base.SendGroupBroadcast(DataTerminal, DataGroup, DataBody, DataTerminalName, conn, DataGUID, MsgNO, DataType == "G"); if (IsPushMode) { DataTable UserList = conn.OpenDataTable("select a.msg_to from lrmsgstate a (nolock) where a.msg_no=" + MsgNO + " and a.msg_state='0'", CommandType.Text); if (UserList.Rows.Count > 0) { string Users = ""; //系統將訊息轉發給群成員(以發送者的帳號) //問題: 1.只有帳號沒有姓名.Client無法顯示姓名 // 2.沒有發送日期和時間 // PC 和 Mobile 要用到的信息.提前打包好,沒必要放到for循環里去做 List<byte[]> msgs = ParseProtocol.ConvertMsgToByte(DataBody, "4", DataTerminal, DataTerminalName, DataGroup, MsgGUID, MsgNO); // Web 要用到的信息.提前打包好,沒必要放到for循環里去做 - 暫時不實現 //byte[] msgw = WebConvertMethod.ConvertMsgToByte(DataBody, "4", DataTerminal, DataTerminalName, DataGroup, MsgNO); foreach (DataRow User in UserList.Rows) { #region " PC Client " Users = PushMessage(Users, msgs, User["msg_to"].ToString(), m_asyncSocketServer.PcUserTokenList, "SendGroupBroadcast"); #endregion #region " Mobile Client " Users = PushMessage(Users, msgs, User["msg_to"].ToString(), m_asyncSocketServer.MobileUserTokenList, "SendGroupBroadcast"); #endregion #region " Web Client " //recUser = _ws_transmit_tb[User["msg_to"].ToString()] as UserSocket; //if (recUser != null) //{ // userSkt = recUser.Socket; // //放到for循環外面去,提高效率 // //byte[] msg = WebConvertMethod.ConvertMsgToByte(DataBody, "4", DataTerminal, DataTerminalName, DataGroup, MsgNO); // try // { // //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 // lock (userSkt) // { // userSkt.Send(msgw); // //SendData(userSkt, msg); // } // Users += "'" + User["msg_to"].ToString() + "',"; // } // catch (SocketException ex) // { // //掉線了,直接干掉. // try // { // //clsClientLog.WriteLog(clsClientLog.LogType.Error, "WebThreadFunc(object obj):catch (SocketException)", "轉發群消息給用戶:" + User["msg_to"].ToString() + "時發生異常,斷開連接."); // LogHelper.WriteLog("SendGroupBroadcast", "轉發群消息給手機用戶:" + User["msg_to"].ToString() + "時發生異常,斷開連接." + (ex != null ? ex.Message : "")); // try // { // if (userSkt.Connected) // { // userSkt.Shutdown(SocketShutdown.Both); // //userSkt.Disconnect(false); // } // userSkt.Close(); // #region " 聯絡人狀態變更 " // //通知在線的聯絡人當前用戶改變了狀態 // //recUser.SetUserState("6"); // //UpdateUserLog(recUser.ID, "1", "1", "Mobile端異常登出"); // //如果PC端沒在線就通知聯絡人此人離線了 // ProcessWebUserState(recUser); // //UserSocket PCUser = _transmit_tb[recUser.ID] as UserSocket; // //if (PCUser == null) // //{ // // SendUserState(recUser); // // UpdateUserState(recUser.ID, "6"); //離線 // //} // #endregion // lock (_ws_transmit_tb.SyncRoot) // _ws_transmit_tb.Remove(User["msg_to"].ToString()); // Thread userThread = _ws_thread_tb[User["msg_to"].ToString()] as Thread; // userThread.Abort(); // //線程池不會被遍歷,不鎖. // _ws_thread_tb.Remove(User["msg_to"].ToString()); // } // catch // { } // } // catch // { } // } //} #endregion } // 去掉最後一個逗號 if (Users.Length > 0) { Users = Users.Substring(0, Users.Length - 1); // 標記為已讀 DateTime now = DateTime.Now; string ymd = now.ToString("yyyy/MM/dd"); string time = now.ToString("HH:mm:ss"); conn.ExecuteSQL("update a set a.msg_state='1',a.ie_lymd='" + ymd + "',a.ie_ltime='" + time + "' from lrmsgstate a where a.msg_no=" + MsgNO + " and a.msg_state='0' and a.msg_to in (" + Users + ")"); } } UserList.Dispose(); UserList = null; } //處理同一帳號多個端登錄的轉發. if (m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.PC || m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.APP) { //來自PC端消息. //檢查相同帳號Mobile(Web)端有沒有登錄,有就轉發一次. #region " Web Client " //recUser = _ws_transmit_tb[DataTerminal] as UserSocket; //if (recUser != null) //{ // userSkt = recUser.Socket; // // 系統將訊息轉發給群成員(以發送者的帳號) // //問題: 1.只有帳號沒有姓名.Client無法顯示姓名 // // 2.沒有發送日期和時間 // byte[] msg = WebConvertMethod.ConvertMsgToByte(DataBody, "4", "", "", DataGroup, MsgNO); // try // { // //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 // lock (userSkt) // { // userSkt.Send(msg); // //SendData(userSkt, msg); // } // } // catch (SocketException ex) // { // //掉線了,直接干掉. // try // { // LogHelper.WriteLog("SendGroupBroadcast", "轉發群消息給手機用戶:" + DataTerminal + "時發生異常,斷開連接." + (ex != null ? ex.Message : "")); // //clsClientLog.WriteLog(clsClientLog.LogType.Error, "WebThreadFunc(object obj):catch (SocketException)", "轉發群消息給Mobile端用戶:" + DataTerminal + "時發生異常,斷開連接."); // if (userSkt.Connected) // { // userSkt.Shutdown(SocketShutdown.Both); // //userSkt.Disconnect(false); // } // userSkt.Close(); // #region " 聯絡人狀態變更 " // //通知在線的聯絡人當前用戶改變了狀態 // //recUser.SetUserState("6"); // //UpdateUserLog(recUser.ID, "1", "1", "Mobile端異常登出"); // //如果PC端沒在線就通知聯絡人此人離線了 // ProcessWebUserState(recUser); // //UserSocket PCUser = _transmit_tb[recUser.ID] as UserSocket; // //if (PCUser == null) // //{ // // SendUserState(recUser); // // UpdateUserState(recUser.ID, "6"); //離線 // //} // #endregion // lock (_ws_transmit_tb.SyncRoot) // _ws_transmit_tb.Remove(DataTerminal); // Thread userThread = _ws_thread_tb[DataTerminal] as Thread; // userThread.Abort(); // //線程池不會被遍歷,不鎖. // _ws_thread_tb.Remove(DataTerminal); // } // catch // { } // } //} #endregion #region " Mobile Client " PushRoaming(DataTerminal, ParseProtocol.ConvertMsgToByte(DataBody, "4", "", "", DataGroup, MsgGUID, MsgNO, "R"), m_asyncSocketServer.MobileUserTokenList); #endregion } if (m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.Mobile || m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.APP) { //來自Mobile(Web)端消息. //檢查相同帳號Web端有沒有登錄,有就轉發一次. #region " PC Client " PushRoaming(DataTerminal, ParseProtocol.ConvertMsgToByte(DataBody, "4", "", "", DataGroup, MsgGUID, MsgNO, "R"), m_asyncSocketServer.PcUserTokenList); #endregion } // 轉發完再發回執 // 向發送者發送回執7-03 this.PushFeedback(MsgGUID, MsgNO); } conn.CloseConnection(); } catch { conn.CloseConnection(); } } }
/// <summary> /// 一次性設置用戶狀態 /// </summary> /// <param name="UserID"></param> /// <param name="conn"></param> /// <param name="State"></param> private void UpdateUsersState(string State) { using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { conn.ExecuteSQL("update a set a.user_state='" + State + "' from lrtduser a"); conn.CloseConnection(); } catch { conn.CloseConnection(); } } }
/// <summary> /// 轉發用戶命令到訂閱號 /// </summary> /// <param name="DataTerminal"></param> /// <param name="DataGroup"></param> /// <param name="DataGUID"></param> /// <param name="DataBody"></param> /// <param name="DataTerminalName"></param> /// <param name="conn"></param> /// <param name="MsgNO"></param> protected void SendRequestToSubService(string DataTerminal, string DataGroup, string DataBody, string DataTerminalName, string MsgGUID, bool SaveMSG) { string MsgNO = ""; // 抓出群成員 if (SaveMSG) { // 只有真正來自用戶的請求才會被記錄到數據庫中. // 由後臺模擬用戶請求則不記錄到數據庫,也不會進行用戶多端設備漫遊 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 // DataType == "L"時, DataTerminalName為Pull消息子分類(表名) MsgNO = this.InsertMsg(conn, DataTerminal, DataBody, DataGroup, "", "1", MsgGUID, false, false); if (MsgNO.Length > 0) { //處理同一帳號多個端登錄的轉發. if (m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.PC || m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.APP) { //來自PC端消息. //檢查相同帳號Mobile(Web)端有沒有登錄,有就轉發一次. #region " Mobile Client " PushRoaming(DataTerminal, ParseProtocol.ConvertMsgToByte(DataBody, "4", "", "", DataGroup, MsgGUID, MsgNO, "R"), m_asyncSocketServer.MobileUserTokenList); #endregion } if (m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.Mobile || m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.APP) { //來自Mobile(Web)端消息. //檢查相同帳號Web端有沒有登錄,有就轉發一次. #region " PC Client " PushRoaming(DataTerminal, ParseProtocol.ConvertMsgToByte(DataBody, "4", "", "", DataGroup, MsgGUID, MsgNO, "R"), m_asyncSocketServer.PcUserTokenList); #endregion } } conn.CloseConnection(); } catch { conn.CloseConnection(); } } } else { MsgNO = "n/a"; } try { //用戶向訂閱號發命令 if (m_asyncSocketServer.SubServiceTokenList.ContainsKey("#" + DataGroup + "#")) { #region " 訂閱號在運行中則繼續作業 " try { SocketUserToken SubSrvToken = m_asyncSocketServer.SubServiceTokenList["#" + DataGroup + "#"]; Socket subSrvSkt = SubSrvToken.ConnectSocket; List<byte[]> msgs = ParseProtocol.ConvertMsgToByte(DataBody, "W", DataTerminal, DataTerminalName, DataGroup, "N/A", "-1"); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 if (subSrvSkt.Connected) { lock (subSrvSkt) { foreach (byte[] msg in msgs) { SubSrvToken.AsyncSendAgent.DoSendBuffer(msg); } } } } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "ThreadFunc(object obj):default", "發送消息回執時:" + ex.Message); LogHelper.WriteLog("SendRequestToSubService", "發送7-09消息回執時:" + (ex != null ? ex.Message : "")); //7-09:訂閱號已經停止工作 PushSubSrvFeedback(DataGroup); } #endregion } else { #region " 訂閱號未運行,向用戶返回信息" //7-09:訂閱號已經停止工作 //PushSubSrvFeedback(DataGroup); SendSubServiceFeedbackToUser(DataTerminal, DataGroup, "訂閱號已經停止工作\r\nSubscription service is not available.", Guid.NewGuid().ToString().Replace("-", "").ToUpper()); #endregion } // 轉發完再發回執 // 向發送者發送回執7-03 this.PushFeedback(MsgGUID, MsgNO); } catch { } }
public void Start(IPEndPoint localEndPoint) { listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listenSocket.Bind(localEndPoint); listenSocket.Listen(m_maxServerLoading); //LogHelper.WriteLog("Start", "服務器已啟動,正在監聽..."); LogHelper.WriteLog("Start", string.Format("服務器已啟動,正在監聽IP: {0} 端口號: {1}", localEndPoint.Address.ToString(), localEndPoint.Port.ToString())); //測試時如果數據庫為正式區,這句不能執行. UpdateUsersState("6"); //全部離線 //測試時如果數據庫為正式區,這句不能執行. #region " 檢查lrtdseq是否添加 并 生成系統廣播" try { using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { //DataTable test = conn.OpenDataTable("declare @seqNO bigint exec GetMessageNO '1',@seqNO output select @seqNO", CommandType.Text); //if (test.Rows.Count > 0) //{ //} DataTable dtSeq = conn.OpenDataTable("select seq_no from lrtdseq (nolock) where seq_type='1'", CommandType.Text); if (dtSeq.Rows.Count > 0) { // SeqNO = long.Parse(dtSeq.Rows[0]["seq_no"].ToString()); // clsClientLog.WriteLog(clsClientLog.LogType.System, hostName, "消息起始ID: " + SeqNO.ToString()); } else { conn.ExecuteSQL("insert into lrtdseq (seq_type,seq_no) values('1',0)"); //clsClientLog.WriteLog(clsClientLog.LogType.System, hostName, "消息起始ID: 0"); LogHelper.WriteLog("WebThreadFunc", "正式區消息起始ID:0"); } ////For Test //dtSeq = conn.OpenDataTable("select seq_no from lrtdseq (nolock) where seq_type='2'", CommandType.Text); //if (dtSeq.Rows.Count > 0) //{ // // SeqNO = long.Parse(dtSeq.Rows[0]["seq_no"].ToString()); // // clsClientLog.WriteLog(clsClientLog.LogType.System, hostName, "消息起始ID: " + SeqNO.ToString()); //} //else //{ // conn.ExecuteSQL("insert into lrtdseq (seq_type,seq_no) values('2',0)"); // //clsClientLog.WriteLog(clsClientLog.LogType.System, hostName, "消息起始ID: 0"); // LogHelper.WriteLog("WebThreadFunc", "測試區消息起始ID:0"); //} // 生成系統公告 dtSeq = conn.OpenDataTable("select * from lrbroadcast (nolock) where bdc_cmd = '1' order by region_id,bdc_seq", CommandType.Text); if (dtSeq.Rows.Count > 0) { DataTable dtRegions = dtSeq.DefaultView.ToTable(true, "region_id"); foreach (DataRow drRegion in dtRegions.Rows) { DataRow[] dtRows = dtSeq.Select("region_id = '" + drRegion["region_id"].ToString() + "'", "bdc_seq"); if (dtRows.Length > 0) { List<NoticeMsg> nMsgs = new List<NoticeMsg>(); foreach (DataRow dr in dtRows) { nMsgs.Add(new NoticeMsg() { MsgSeq = dr["bdc_seq"].ToString(), MsgText = dr["bdc_text"].ToString() }); } this.SysNotices.Add(drRegion["region_id"].ToString(), nMsgs); } } dtRegions.Dispose(); dtRegions = null; } dtSeq.Dispose(); dtSeq = null; conn.CloseConnection(); } catch { conn.CloseConnection(); } } } catch (Exception ex) { //clsClientLog.WriteLog(clsClientLog.LogType.System, hostName, "獲得消息起始ID失敗.原因: " + ex.Message); LogHelper.WriteLog("WebThreadFunc", "獲得消息起始ID失敗.原因:" + (ex != null ? ex.Message : "")); return; } #endregion #region " 開一個獨立的線程來定時發送1.活動用戶數,2.在線用戶數,3註冊用戶數,4.今日消息數,5.累積消息數 " SysThread = new Thread(SysTreadFunc); SysThread.Start(); #endregion // 開一個線程來標記歷史消息為已讀 MarkReadThread = new Thread(MarkReadThreadFunc); MarkReadThread.Start(); // 開一個線程來推送用戶在線狀態 // 初始化-MaxStateNotifyThreads for (int i = 0; i < MaxStateNotifyThreads; i++) { StateNofityThreadsQueue.Enqueue(new Thread(new ParameterizedThreadStart(StateNotifyThreadFunc))); } StateNotifyControlThread = new Thread(StateNotifyControlThreadFunc); StateNotifyControlThread.Priority = ThreadPriority.AboveNormal; // 次高級 StateNotifyControlThread.Start(); // 開一個線程來更新數據類群信息 UpdateVDataThread = new Thread(UpdateVDataThreadFunc); UpdateVDataThread.Start(); StartAccept(null); //未完成 //守護線程 //m_daemonThread = new DaemonThread(this); }
/// <summary> /// 轉發訂閱號回覆到用戶 /// </summary> /// <param name="DataTerminal"></param> /// <param name="DataGroup"></param> /// <param name="DataBody"></param> /// <param name="DataGUID"></param> protected void SendSubServiceFeedbackToUser(string DataTerminal, string DataGroup, string DataBody, string MsgGUID) { // 抓出群成員 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 // DataType == "L"時, DataTerminalName為Pull消息子分類(表名) string MsgNO = this.InsertSubSrvFeedback(conn, m_userToken.BindingUser.ID, DataBody, DataGroup, DataTerminal, "0", "", "1", "0", MsgGUID); if (MsgNO.Length > 0) { #region " 發給接收人 " DataTable UserList = conn.OpenDataTable("select a.msg_to from lrmsgstate a (nolock) where a.msg_no=" + MsgNO + " and a.msg_state='0'", CommandType.Text); if (UserList.Rows.Count > 0) { string Users = ""; //系統將訊息轉發給群成員(以發送者的帳號) //問題: 1.只有帳號沒有姓名.Client無法顯示姓名 // 2.沒有發送日期和時間 // PC 和 Mobile 要用到的信息.提前打包好,沒必要放到for循環里去做 List<byte[]> msgs = ParseProtocol.ConvertMsgToByte(DataBody, "5", "", "", DataGroup, MsgGUID, MsgNO); foreach (DataRow User in UserList.Rows) { #region " PC Client " Users = PushMessage(Users, msgs, User["msg_to"].ToString(), m_asyncSocketServer.PcUserTokenList, "SendSubServiceFeedbackToUser"); #endregion #region " Mobile Client " Users = PushMessage(Users, msgs, User["msg_to"].ToString(), m_asyncSocketServer.MobileUserTokenList, "SendSubServiceFeedbackToUser"); #endregion } // 去掉最後一個逗號 if (Users.Length > 0) { Users = Users.Substring(0, Users.Length - 1); // 標記為已讀 DateTime now = DateTime.Now; string ymd = now.ToString("yyyy/MM/dd"); string time = now.ToString("HH:mm:ss"); conn.ExecuteSQL("update a set a.msg_state='1',a.ie_lymd='" + ymd + "',a.ie_ltime='" + time + "' from lrmsgstate a where a.msg_no=" + MsgNO + " and a.msg_state='0' and a.msg_to in (" + Users + ")"); } } UserList.Dispose(); UserList = null; #endregion // 轉發完再發回執 // 向發送者發送回執7-03 //this.PushFeedback(MsgGUID, MsgNO); } conn.CloseConnection(); } catch { conn.CloseConnection(); } } }
/// <summary> /// 排程處理用戶狀態推送 /// </summary> private void StateNotifyControlThreadFunc() { SQLHelper conn = new SQLHelper(DBInfo); //DataTable ContactsList; //SocketUserToken UserToken; string UserID, UserState, UserSignature; byte[] UserAvatar = null; List<string> Contacts; try { conn.OpenConnection(); while (true) { Thread.Sleep(100); try { //當前設備數據更新隊列 ServerStatistics.CurentUserState_Queue = StateNotifyQueue.Count; //最高設備數據更新隊列 if (ServerStatistics.MaxUserState_Queue < ServerStatistics.CurentUserState_Queue) ServerStatistics.MaxUserState_Queue = ServerStatistics.CurentUserState_Queue; //可用的用戶狀態推送線程 ServerStatistics.IdleUserState_PushQueue = StateNofityThreadsQueue.Count; while (StateNotifyQueue.Count > 0 && StateNofityThreadsQueue.Count > 0) { //有用戶在排隊 //User = (UserSocket)StateNotifyQueue.Dequeue(); List<object> objs = (List<object>)StateNotifyQueue.Dequeue(); if (objs != null) { //UserToken = (SocketUserToken)objs[0]; UserID = objs[0].ToString(); UserState = objs[1].ToString(); UserSignature = objs[2].ToString(); Contacts = (List<string>)objs[3]; //Added by Donnie on 2016/04/27 UserAvatar = (byte[])objs[4]; //頭像數據 //if (UserToken.BindingUser.Contacts.Count == 0) //{ // ContactsList = GetContacts(conn, UserToken.BindingUser.ID); // if (ContactsList.Rows.Count > 0) // { // foreach (DataRow Contact in ContactsList.Rows) // { // //加入聯絡人(防呆自己加自己) // if (UserToken.BindingUser.ID != Contact["contact_id"].ToString()) // UserToken.BindingUser.Contacts.Add(Contact["contact_id"].ToString()); // } // } //} if (Contacts.Count > 0) { if (StateNofityThreadsQueue.Count > 0) { //有空閒的線程可以使用 //取出線程和用戶并開始推送操作 Thread StateNotifyThread = (Thread)StateNofityThreadsQueue.Dequeue(); if (StateNotifyThread != null) { //LogHelper.WriteLog("StateNotifyControlThreadFunc", "已取得線程資源,即將推送" + User.ID + "的狀態" + UserState); List<object> paras = new List<object>(); //不再打包UserToken,因為如果是用戶離線操作,有可能狀態還沒有推送前UserToken就已經被消除了.推送時會因無法抓UserToken而報錯. //paras.Add(UserToken); paras.Add(UserID); //ID string paras.Add(UserState); //狀態 string paras.Add(UserSignature); //簽名 string paras.Add(Contacts); //聯絡人清單 List<string> paras.Add(UserAvatar); //頭像數據 paras.Add(StateNotifyThread); //工作線程 Thread if (!StateNotifyThread.IsAlive) { StateNotifyThread = new Thread(new ParameterizedThreadStart(StateNotifyThreadFunc)); } StateNotifyThread.Start(paras); } else { // 沒有取到線程資源,把對象重新放入隊列 StateNotifyQueue.Enqueue(objs); LogHelper.WriteLog("StateNotifyControlThreadFunc", "沒有取到線程資源,把對象重新放入隊列."); } } else { // 沒有可用的線程資源,把對象重新放入隊列 StateNotifyQueue.Enqueue(objs); LogHelper.WriteLog("StateNotifyControlThreadFunc", "沒有可用的線程資源,把對象重新放入隊列."); } } } } } catch (Exception ex) { LogHelper.WriteLog("StateNotifyControlThreadFunc()", "執行用戶狀態推送時:" + (ex != null ? ex.Message : "")); } } } catch (Exception ex) { LogHelper.WriteLog("StateNotifyControlThreadFunc()", "執行用戶狀態推送時:" + (ex != null ? ex.Message : "")); } finally { if (conn != null) conn.CloseConnection(); } }
protected string ProcessTransferFileRequest(string Target, string DataType, string DataTerminal, string DataGroup, string DataGUID, string DataBody, string DataTerminalName) { string MsgNO = ""; // 記錄到數據庫中 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { //msg_doctype = 0:即時文件 1:文字 2:離線文件 //msg_docstate = 3:等待接收 2:傳送完成 if (DataGroup != "O") { MsgNO = this.InsertMsg(conn, Target, DataBody, "", DataTerminal, "1", "", "0", "3", DataGUID, false, true); } else { MsgNO = this.InsertMsg(conn, Target, DataBody, "", DataTerminal, "1", "", "2", "2", DataGUID, false, true); } conn.CloseConnection(); if (MsgNO.Length > 0) { //接收者 PushMessage("", ParseProtocol.ConvertMsgToByte(DataBody, DataType, Target, DataTerminalName, DataGroup, DataGUID, MsgNO), DataTerminal, m_asyncSocketServer.PcUserTokenList, "ProcessTransferFileRequest"); #region " 處理同一帳號多個端登錄的轉發. " if (DataGroup == "O" && m_userToken.BindingUser.Role == LxTcpServer.Core.User.UserRole.APP) { //來自Mobile(Web)端消息. //檢查相同帳號Web端有沒有登錄,有就轉發一次. #region " PC Client " PushRoaming(Target, ParseProtocol.ConvertMsgToByte(DataBody, "P", DataTerminal, "", "", DataGUID, MsgNO, "R"), m_asyncSocketServer.PcUserTokenList); #endregion } #endregion } } catch { conn.CloseConnection(); } } return MsgNO; }
public static string[] ProcessRequest(object[] requestData, string SrvNO, string DBAlias) { //20條數據分一頁,防止單條消息超過4000byte int ROWS_PER_PAGE = 20; //返回數組 0=type ; 1=終端; 2=群號; 3=時間; 4=消息ID; 5=消息內容 6=終端姓名 string result = "無效命令." + Environment.NewLine + "請使用命令: ? 查詢本訂閱號提供的服務."; //訂閱號業務處理分類處理 //訂閱號,命令Code,操作腳本 //switch (GroupID) //{ // case "888": // //在這里加入解析命令并處理 // //Do something // result = "SubSrv #1:Hello"; // break; // case "D151100318": // //在這里加入解析命令并處理 // //Do something // result = "SubSrv #2:Hello"; // break; //} if (requestData[5].ToString().Trim() == "?" || requestData[5].ToString().Trim() == "?") { #region " ?命令:返回訂閱號的命令清單 " using (SQLHelper conn = new SQLHelper(DBAlias)) { conn.OpenConnection(); try { DataTable Rec = conn.OpenDataTable("select cmd_code,cmd_remk,cmd_format from lxsubcmds (nolock) where srv_no='" + SrvNO + "' and cmd_visible='Y' order by cmd_seq", CommandType.Text); conn.CloseConnection(); if (Rec.Rows.Count > 0) { //<table> // <caption>訂閱號命令清單</caption> // <thead> // <tr> // <th>命令代碼</th> // <th>命令說明</th> // <th>命令格式</th> // </tr> // </thead> // <tbody> // <tr> // <td>FILE</td> // <td>列出EIS報表代號及名稱清單</td> // <td>FILE</td> // </tr> // <tr> // <td>EIS</td> // <td>取得EIS系統資料</td> // <td>EIS EIC-ID-003 A169 2016/06</td> // </tr> // </tbody> //</table> string h5_Table_Format = "<table>" + "\r\n" + " <caption>訂閱號命令清單{0}</caption>" + "\r\n" + " <thead>" + "\r\n" + " <tr>" + "\r\n" + " <th style=\"width:80px;\">命令代碼</th>" + "\r\n" + " <th style=\"width:auto;\">命令說明</th>" + "\r\n" + " <th style=\"width:auto;\">命令格式</th>" + "\r\n" + " </tr>" + "\r\n" + " </thead>" + "\r\n" + " <tbody>" + "\r\n" + " {1}" + "\r\n" + " </tbody>" + "\r\n" + "</table>"; string h5_tBody_Format = "<tr>" + "\r\n" + " {0}" + "\r\n" + "</tr>"; result = ""; //string h5_Head_Value = ""; List<string> CmdRows = new List<string>(); for (int i = 0; i < Rec.Rows.Count; i++) { //result += Rec.Rows[i]["cmd_code"].ToString() + " : " + Rec.Rows[i]["cmd_remk"].ToString(); //h5_Head_Value += string.Format(h5_tBody_Format, "<td>" + Rec.Rows[i]["cmd_code"].ToString() + "</td>" + // "<td>" + Rec.Rows[i]["cmd_remk"].ToString() + "</td>" + // "<td>" + Rec.Rows[i]["cmd_format"].ToString() + "</td>") + Environment.NewLine; //if (i + 1 < Rec.Rows.Count) // result += Environment.NewLine; CmdRows.Add(string.Format(h5_tBody_Format, "<td>" + Rec.Rows[i]["cmd_code"].ToString() + "</td>" + "<td>" + Rec.Rows[i]["cmd_remk"].ToString() + "</td>" + "<td>" + Rec.Rows[i]["cmd_format"].ToString() + "</td>")); } //得到消息條數 string[] Results = new string[CmdRows.Count / ROWS_PER_PAGE + 1]; int k = 0; for (int i = 0; i < CmdRows.Count; i++) { if (i % ROWS_PER_PAGE == 0 && i > 0) { //達到分頁數,產生一條消息. Results[k] = string.Format(h5_Table_Format, "(" + (k+1).ToString() + ")", result); k++; result = ""; } result += CmdRows[i] + Environment.NewLine; } if (result.Length > 0 && k < Results.Length) { //最後一筆 Results[k] = string.Format(h5_Table_Format, "(" + (k + 1).ToString() + ")", result); } CmdRows.Clear(); CmdRows = null; //result = "本訂閱號命令如下:" + Environment.NewLine + result; //result = string.Format(h5_Table_Format, h5_Head_Value); //直接返回 return Results; } else { result = "本訂閱號暫無命令可使用."; } } catch (Exception ex) { LogHelper.WriteLog("ProcessRequest()", "處理?命令時:" + (ex != null ? ex.Message : "")); conn.CloseConnection(); } } #endregion } else if (requestData[5].ToString().Trim().IndexOf("<Data Name=") > -1 && requestData[5].ToString().Trim().IndexOf("</Data>") > -1) { //格式化輸入不響應 result = ""; } else { #region " 其他命令 " //select cmd_operation,cmd_paras from lxsubcmds (nolock) where srv_no='3737' and cmd_code='PO' using (SQLHelper conn = new SQLHelper(DBAlias)) { conn.OpenConnection(); try { //空格分隔 string[] tmp = requestData[5].ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); //命令 string CMD = tmp[0].Trim().ToUpper(); //規則: //1.用命令得到訂閱號表名及欄位. DataTable Rec = conn.OpenDataTable("select cmd_operation,cmd_paras,srv_table,filter_key,order_key,top_num,template_no,match_type,multi_value,cmd_format,rows_paging from lxsubcmds (nolock) where srv_no='" + SrvNO + "' and cmd_code='" + CMD + "'", CommandType.Text); if (Rec.Rows.Count > 0) { //得到分頁靈敏 ROWS_PER_PAGE = int.Parse(Rec.Rows[0]["rows_paging"].ToString()); if (ROWS_PER_PAGE <= 0) ROWS_PER_PAGE = 20; //2.得到權限分組代號 DataTable subRec = conn.OpenDataTable("select permission_group from lxpermissions (nolock) where srv_no='" + SrvNO + "' and lx_account='" + requestData[1].ToString().Trim() + "'", CommandType.Text); if (subRec.Rows.Count > 0) { string andWhere = "", OrderBy = ""; //1=等於;2=以..開始 string MathType = Rec.Rows[0]["match_type"].ToString(); string SrvTable = Rec.Rows[0]["srv_table"].ToString(); string CMDFormat = Rec.Rows[0]["cmd_format"].ToString(); string PermissionGroup = ""; for (int i = 0; i < subRec.Rows.Count; i++) { PermissionGroup += "'" + subRec.Rows[i]["permission_group"].ToString() + "'"; if (i + 1 < subRec.Rows.Count) PermissionGroup += ","; } //3.根據表名得到參數名 subRec = conn.OpenDataTable("select tb_colno,tb_colna,tb_coltype from lxsubtemplates (nolock) where srv_no='" + SrvNO + "' and srv_table='" + SrvTable + "' and template_no='" + Rec.Rows[0]["template_no"].ToString() + "' order by paras_order", CommandType.Text); if (subRec.Rows.Count > 0) { //4.得到訂閱號表數據(lxsub01,lxsub02...) (根據filter_key,order_key,top_num抓數據) result = GetFilterAndOrder(tmp, CMD, Rec, ref andWhere, ref OrderBy, MathType); if (result.Length == 0) { DataTable dataRec = conn.OpenDataTable("select " + Rec.Rows[0]["top_num"].ToString() + " * from " + SrvTable + " (nolock) where srv_no='" + SrvNO + "' and group_no in (" + PermissionGroup + ")" + andWhere + OrderBy, CommandType.Text); if (dataRec.Rows.Count > 1) { #region " 明細 " string h5_Table_Format = "<table>" + "\r\n" + " <caption>{0}{1}</caption>" + "\r\n" + " <thead>" + "\r\n" + " <tr>" + "\r\n" + " {2}" + "\r\n" + " </tr>" + "\r\n" + " </thead>" + "\r\n" + " <tbody>" + "\r\n" + " {3}" + "\r\n" + " </tbody>" + "\r\n" + "</table>"; string h5_tBody_Format = "<tr>" + "\r\n" + " {0}" + "\r\n" + "</tr>"; //得到cmd_operation,并把轉換為橫多行模式 //<table> // <caption>項目回報表</caption> // <thead> // <tr> // <th>序號</th> // <th>工作人員</th> // <th>項目編號</th> // <th>項目名稱</th> // <th>立案日期</th> // <th>備注</th> // </tr> // </thead> // <tbody> // <tr> // <td>0001</td> // <td>D003842</td> // <td>T0000001</td> // <td>樂行樂信底層開發</td> // <td>2016/01/01</td> // <td>進行中</td> // </tr> // <tr> // <td>0002</td> // <td>D003842</td> // <td>T0000002</td> // <td>樂行樂信第三方應用開發</td> // <td>2016/01/01</td> // <td>進行中</td> // </tr> // </tbody> //</table> string h5_Table_Caption = ""; //{0} string h5_Head_Value = ""; //{1} result = ""; List<string> CmdRows = new List<string>(); //得到顯示列表樣式 DataTable ListFormat = XmlStrToDataTable(subRec, Rec.Rows[0]["cmd_operation"].ToString()); decimal width = 0; if (ListFormat != null && ListFormat.Rows.Count > 0) { h5_Table_Caption = HtmlConvertor(ListFormat.ExtendedProperties["Caption"].ToString()); //<th>序號</th> foreach (DataRow dr in ListFormat.Rows) { try { width = decimal.Parse(dr["tb_colwidth"].ToString()); } catch { width = 0; } if (width <= 0) width = 80; h5_Head_Value += "<th style=\"width:" + width.ToString() + "px;\">" + dr["tb_colna"].ToString() + "</th>"; } //開始填表身數據 string colno = ""; //string h5_Body_Value = ""; //{0} string h5_Body_Value_tmp = ""; foreach (DataRow row in dataRec.Rows) { h5_Body_Value_tmp = ""; for (int i = 0; i < subRec.Rows.Count; i++) { colno = subRec.Rows[i]["tb_colno"].ToString(); if (subRec.Rows[i]["tb_coltype"].ToString() == "1") { //FTP文件 h5_Body_Value_tmp += "<td>" + "ftp://lx.lorom.net.cn/ProductAttatchments/ToDoList/" + SrvNO + "/" + row[colno].ToString() + "</td>"; } else { h5_Body_Value_tmp += "<td>" + HtmlConvertor(row[colno].ToString()) + "</td>"; } } CmdRows.Add(string.Format(h5_tBody_Format, h5_Body_Value_tmp)); //h5_Body_Value += string.Format(h5_tBody_Format, h5_Body_Value_tmp) + "\r\n"; } //得到消息條數 string[] Results = new string[(CmdRows.Count % ROWS_PER_PAGE == 0) ? (CmdRows.Count / ROWS_PER_PAGE) : (CmdRows.Count / ROWS_PER_PAGE + 1)]; int k = 0; for (int i = 0; i < CmdRows.Count; i++) { if (i % ROWS_PER_PAGE == 0 && i > 0) { //達到分頁數,產生一條消息. Results[k] = string.Format(h5_Table_Format, h5_Table_Caption, "(" + (k + 1).ToString() + ")", h5_Head_Value, result); k++; result = ""; } result += CmdRows[i] + Environment.NewLine; } if (result.Length > 0 && k < Results.Length) { //最後一筆 Results[k] = string.Format(h5_Table_Format, h5_Table_Caption, "(" + (k + 1).ToString() + ")", h5_Head_Value, result); } CmdRows.Clear(); CmdRows = null; //組成最後的列表 //result = string.Format(h5_Table_Format, h5_Table_Caption, // h5_Head_Value, // h5_Body_Value); //直接返回一條或多條. return Results; } else { LogHelper.WriteLog("ProcessRequest()", "嘗試命令:" + CMD + "的cmd_operation參數設置錯誤."); result = "對不起,當前命令暫時無法使用."; } #endregion } else if (dataRec.Rows.Count == 1) { #region " 單筆 " string[] paras = new string[subRec.Rows.Count]; string colno = ""; for (int i = 0; i < subRec.Rows.Count; i++) { colno = subRec.Rows[i]["tb_colno"].ToString(); if (subRec.Rows[i]["tb_coltype"].ToString() == "1") { //FTP文件 paras[i] = "ftp://lx.lorom.net.cn/ProductAttatchments/ToDoList/" + SrvNO + "/" + dataRec.Rows[0][colno].ToString(); } else { paras[i] = HtmlConvertor(dataRec.Rows[0][colno].ToString()); } } result = string.Format(Rec.Rows[0]["cmd_operation"].ToString(), paras); #endregion } else { result = "對不起,暫時無法取得任何數據."; } } else { //命令格式不正確 result += CMDFormat; return new string[] { result }; } } else { LogHelper.WriteLog("ProcessRequest()", "命令:" + CMD + "的cmd_operation參數設置錯誤."); result = "對不起,當前命令暫時無法使用."; } #region " 舊邏輯 " //if (Rec.Rows[0]["multi_value"].ToString() == "Y" && subRec.Rows.Count > 0) //{ // #region " 明細類數據 " // //4.得到訂閱號表數據(lxsub01,lxsub02...) (根據filter_key,order_key,top_num抓數據) // result = GetFilterAndOrder(tmp, CMD, Rec, ref andWhere, ref OrderBy, MathType); // if (result.Length > 0) // { // //命令格式不正確 // result += CMDFormat; // return result; // } // DataTable dataRec = conn.OpenDataTable("select * from " + SrvTable + " (nolock) where srv_no='" + SrvNO + "' and group_no in (" + PermissionGroup + ")" + andWhere + OrderBy, CommandType.Text); // if (dataRec.Rows.Count > 0) // { // string colno = "", colna = ""; // result = ""; // foreach (DataRow row in dataRec.Rows) // { // for (int i = 0; i < subRec.Rows.Count; i++) // { // colno = subRec.Rows[i]["tb_colno"].ToString(); // colna = subRec.Rows[i]["tb_colna"].ToString(); // if (subRec.Rows[i]["tb_coltype"].ToString() == "1") // { // //FTP文件 // result += colna + "ftp://lx.lorom.net.cn/ProductAttatchments/ToDoList/" + SrvNO + "/" + row[colno].ToString(); // } // else // { // result += colna + row[colno].ToString(); // } // if (i + 1 < subRec.Rows.Count) // { // result += " "; // } // } // result += Environment.NewLine; // } // result = string.Format(Rec.Rows[0]["cmd_operation"].ToString(), result); // } // else // { // result = "對不起,暫時無法取得任何數據."; // } // #endregion //} //else //{ // #region " 單筆數據 " // if (subRec.Rows.Count == float.Parse(Rec.Rows[0]["cmd_paras"].ToString()) && subRec.Rows.Count > 0) // { // //參數設置正確 // //4.得到訂閱號表數據(lxsub01,lxsub02...) (根據filter_key,order_key,top_num抓數據) // result = GetFilterAndOrder(tmp, CMD, Rec, ref andWhere, ref OrderBy, MathType); // if (result.Length > 0) // { // //命令格式不正確 // result += CMDFormat; // return result; // } // DataTable dataRec = conn.OpenDataTable("select " + Rec.Rows[0]["top_num"].ToString() + " * from " + SrvTable + " (nolock) where srv_no='" + SrvNO + "' and group_no in (" + PermissionGroup + ")" + andWhere + OrderBy, CommandType.Text); // if (dataRec.Rows.Count > 0) // { // string[] paras = new string[subRec.Rows.Count]; // string colno = ""; // for (int i = 0; i < subRec.Rows.Count; i++) // { // colno = subRec.Rows[i]["tb_colno"].ToString(); // if (subRec.Rows[i]["tb_coltype"].ToString() == "1") // { // //FTP文件 // paras[i] = "ftp://lx.lorom.net.cn/ProductAttatchments/ToDoList/" + SrvNO + "/" + dataRec.Rows[0][colno].ToString(); // } // else // { // paras[i] = dataRec.Rows[0][colno].ToString(); // } // } // result = string.Format(Rec.Rows[0]["cmd_operation"].ToString(), paras); // } // else // { // result = "對不起,暫時無法取得任何數據."; // } // } // else // { // LogHelper.WriteLog("ProcessRequest()", "命令:" + CMD + "的cmd_operation參數設置錯誤."); // result = "對不起,當前命令暫時無法使用."; // } // #endregion //} #endregion } else { result = "對不起,當前帳號無權限使用此命令."; } } conn.CloseConnection(); } catch (Exception ex) { result = "訂閱號服務出現異常,請稍後再試."; LogHelper.WriteLog("ProcessRequest()", "處理: " + requestData[5].ToString() + " 命令時:" + (ex != null ? ex.Message : "")); conn.CloseConnection(); } } #endregion } return new string[] { result }; }
protected void SendImage(string DataTerminal, string DataGroup, byte[] DataImage, string DataTerminalName, string DataGUID) { //處理邏輯: 將圖片生成一個縮略圖,存放到lrtdmsg.msg_img里. 再將完整圖片數據放到對照表lrmsgimg里. // 用戶點擊縮略圖再下載完整圖片 try { int width = ServerConst.Thumbnail_Width, height = ServerConst.Thumbnail_Height; System.Drawing.Image thumbnail = ImageHelper.BytesToImage(ImageHelper.DeCompress(DataImage)); if (thumbnail.Width < width) width = thumbnail.Width; if (thumbnail.Height < height) height = thumbnail.Height; byte[] ThumbImage = ImageHelper.Compress(ImageHelper.Thumbnail(thumbnail, width, height, ServerConst.Thumbnail_Quality, "WH")); thumbnail.Dispose(); thumbnail = null; string curUserID = m_userToken.BindingUser.ID; //DataTerminal是接收人帳號 //DataTerminalName是發送人姓名 using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { // 記錄到數據庫中 string MsgNO = InsertImage(conn, curUserID, DataImage, DataGroup, DataTerminal, "1", DataGUID, ThumbImage); if (MsgNO.Length > 0) { //沒改完,要用特殊方式打包 //開始發送 if (DataGroup.Length == 0) { //向人發 SendP2PImage(curUserID, DataTerminalName, DataTerminal, ThumbImage, conn, DataGUID, MsgNO); } else { //向群發 SendGroupImage(DataTerminal, DataGroup, ThumbImage, DataTerminalName, conn, DataGUID, MsgNO); } // 轉發完再發回執 // 向發送者發送回執7-03 PushFeedback(DataGUID, MsgNO); } conn.CloseConnection(); } catch { conn.CloseConnection(); } } } catch (Exception ex) { LogHelper.WriteLog("SendImage", ex.Message); } }
/// <summary> /// 通話日誌記錄 /// </summary> private void UpdateAudioLog(string SenderID, string ReceiverID, DateTime StartDT, DateTime EndDT, string logGUID, string logSIP, string devSName, string devSMac, string logRIP, string devRName, string devRMac) { using (SQLHelper conn = new SQLHelper(m_asyncSocketServer.DBInfo)) { conn.OpenConnection(); try { DateTime LogDT = DateTime.Now; TimeSpan TS = EndDT.Subtract(StartDT); conn.ExecuteSQL("insert into lxaudiolog (sender_id,receiver_id,ie_ymd,ie_time,log_sdate,log_stime,log_edate,log_etime,log_durtime,log_guid,log_sip,dev_sname,dev_smac,log_rip,dev_rname,dev_rmac) " + "\r\n" + "values('" + SenderID + "','" + ReceiverID + "','" + LogDT.ToString("yyyy/MM/dd") + "','" + LogDT.ToString("HH:mm:ss") + "'," + "\r\n" + "'" + StartDT.ToString("yyyy/MM/dd") + "','" + StartDT.ToString("HH:mm:ss") + "'," + "'" + EndDT.ToString("yyyy/MM/dd") + "','" + EndDT.ToString("HH:mm:ss") + "'," + (int)TS.TotalSeconds + "," + "'" + logGUID + "','" + logSIP + "','" + devSName + "','" + devSMac + "','" + logRIP + "','" + devRName + "','" + devRMac + "')"); conn.CloseConnection(); } catch (Exception ex) { conn.CloseConnection(); throw ex; } } }
/// <summary> /// 線程執行體,登錄驗證 /// </summary> /// <param name="obj"></param> private void ThreadLoginCheckFunc(object objs) { if (objs != null) { //2016/02/27 object obj = ((List<object>)objs)[0]; // 用戶Socket object tobj = ((List<object>)objs)[1]; // 登錄線程 Thread LoginThread = (Thread)tobj; try { string UserID = ""; Socket newClient = obj as Socket; //返回解包后的資料(返回數組 0=type ; 1=終端; 2=群號; 3=時間; 4=消息ID; 5=消息內容; 6=終端姓名) // type = "0" 是PC登錄; type = "WS" 是Web登錄 object[] ReceiveData = ConvertMethod.ParseLoginData(newClient, LoginTimeOut); //ConvertMethod.UnMsgPackage(newClient); string DataType = ReceiveData[0].ToString(); string DataTerminal = ReceiveData[1].ToString(); //普通用戶登錄為空 //APP登錄為APP //訂閱號登錄為SUB(會有一個特別的HashTable來保存訂閱號的連接) string DataGroup = ReceiveData[2].ToString(); string DataTerminalName = ReceiveData[6].ToString(); string DataText = ReceiveData[5].ToString(); if (DataType == "0" && DataTerminal.Length > 0) { //test //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "PC端" + DataTerminal + "請求登錄"); //LogHelper.WriteLog("StartUp()", "PC端用戶: " + DataTerminal + "-" + DataTerminalName + " 請求登錄"); UserID = DataTerminal; // 用戶帳號 bool Passed = true; switch (DataGroup.ToUpper()) { case "SUB": #region " 訂閱號登錄 " //未開工2016/01/26 #endregion break; case "APP": #region " APP登錄 " try { List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("登錄成功.", "2", UserID, DataTerminalName, DataGroup, Guid.NewGuid().ToString().Replace("-", "").ToUpper(), ""); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (newClient) { foreach (byte[] msg in msgs) { newClient.Send(msg); //SendData(newClient, msg); } } } catch (Exception ex) { Passed = false; //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():服務器開放登錄功能", "發送登陸成功信息時:" + ex.Message); LogHelper.WriteLog("StartUp()", "發送登錄成功信息時" + (ex != null ? ex.Message : "")); } if (Passed) { //創建連接對象 UserSocket AppUser = new UserSocket(); AppUser.ID = UserID; AppUser.Socket = newClient; AppUser.State = UserSocket.UserStates.Online; // 將新連接加入轉發表並創建線程為其服務 // Key-GUID永不重複 _app_transmit_tb.Add(UserID, AppUser); try { Thread clientThread = new Thread(new ParameterizedThreadStart(AppThreadFunc)); //加入哈希表 _app_thread_tb.Add(UserID, clientThread); clientThread.Start(UserID); } catch (Exception ex) { try { //清除已加入的連接 _app_transmit_tb.Remove(UserID); } catch { } //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():開啟新線程", "建立登入用戶新線程時:" + ex.Message); LogHelper.WriteLog("StartUp()", "建立登入用戶" + DataTerminal + "-" + DataTerminalName + "新線程時:" + (ex != null ? ex.Message : "")); } } #endregion break; case "MOBILE": LogHelper.WriteLog("ThreadLoginCheckFunc()", "發現非常進入者:" + DataTerminal); #region " 移動端登錄 " UserSocket MobileUser = _mobile_transmit_tb[DataTerminal] as UserSocket; if (MobileUser != null) { Socket curSkt = MobileUser.Socket; #region " 發送離線 " try { List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("00", "7", DataTerminal, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper(), ""); //如果2秒內得不到之前登陸的對象,就直接干掉 //否則此帳號將永遠無法登錄 if (Monitor.TryEnter(curSkt, 2000)) { try { //向用戶本人發送離線 foreach (byte[] msg in msgs) { curSkt.Send(msg); //SendData(curSkt, msg); } } catch { } finally { Monitor.Exit(curSkt); } } else { //如果到這里說明之前登陸的對象已經死鎖 } UpdateUserLog(UserID, "1", "0", "因相同帳號再次登陸而強制離線."); //log //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "相同帳號再次登陸:" + DataTerminal + " " + DataTerminalName); //LogHelper.WriteLog("StartUp()", "相同帳號再次登陸:" + DataTerminal + " " + DataTerminalName); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "轉發用戶" + UserID + "離線消息時:" + ex.Message); LogHelper.WriteLog("ThreadLoginCheckFunc()", "轉發用戶" + UserID + "離線消息時:" + (ex != null ? ex.Message : "")); } try { if (curSkt.Connected) { curSkt.Shutdown(SocketShutdown.Both); //curSkt.Disconnect(false); } curSkt.Close(); curSkt = null; Thread thread = _mobile_thread_tb[DataTerminal] as Thread; if (thread != null) { thread.Abort(); //線程池不會被遍歷,不鎖. _mobile_thread_tb.Remove(DataTerminal); } lock (_transmit_tb.SyncRoot) _mobile_transmit_tb.Remove(DataTerminal); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "嘗試關閉用戶" + DataTerminal + "線程和Socket連接時出錯." + (ex != null ? ex.Message : "")); LogHelper.WriteLog("ThreadLoginCheckFunc()", "嘗試關閉用戶" + DataTerminal + "線程和Socket連接時出錯." + (ex != null ? ex.Message : "")); } #endregion } // 驗證是否為唯一用戶 if (_mobile_transmit_tb.Count != 0 && _mobile_transmit_tb.ContainsKey(UserID)) { try { List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("登錄失敗.", "3", UserID, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper(), ""); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (newClient) { foreach (byte[] msg in msgs) { newClient.Send(msg); //SendData(newClient, msg); } } //test //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "PC端" + DataTerminal + "登錄失敗"); LogHelper.WriteLog("ThreadLoginCheckFunc()", "移動客戶端" + DataTerminal + "登錄失敗"); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():驗證是否為唯一用戶", "發送登陸失敗信息時:" + ex.Message); LogHelper.WriteLog("ThreadLoginCheckFunc()", "發送登陸失敗信息時" + (ex != null ? ex.Message : "")); } } else { // 服務器開放登錄功能 try { List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("登錄成功.", "2", UserID, DataTerminalName, DataGroup, Guid.NewGuid().ToString().Replace("-", "").ToUpper(), ""); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (newClient) { foreach (byte[] msg in msgs) { newClient.Send(msg); //SendData(newClient, msg); } } } catch (Exception ex) { Passed = false; //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():服務器開放登錄功能", "發送登陸成功信息時:" + ex.Message); LogHelper.WriteLog("ThreadLoginCheckFunc()", "發送登錄成功信息時" + (ex != null ? ex.Message : "")); } if (Passed) { //創建連接對象 MobileUser = new UserSocket(); MobileUser.ID = UserID; MobileUser.Socket = newClient; MobileUser.State = UserSocket.UserStates.Online; //登錄時群號規則: 普通用戶登錄時為空格, 手機應用登錄時為"MOBILE" using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { #region " 獲得當前用記的所有聯絡人并向他們推送用戶上線消息 " StateNotifyQueue.Enqueue(new List<object>() { MobileUser, "1" }); #endregion //Test //LogHelper.WriteLog("ThreadLoginCheckFunc()", User.ID + "推送未讀消息."); #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()); // 判斷個人消息還是群消息 List<byte[]> rtnMsgs = ConvertMethod.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) { 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'"); //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("ThreadLoginCheckFunc()", "標識歷史信息為已讀時:" + (ex != null ? ex.Message : "")); } } } //Test LogHelper.WriteLog("ThreadLoginCheckFunc()", "共向移動端用戶:" + MobileUser.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 = ConvertMethod.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) { 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("ThreadLoginCheckFunc()", "標識歷史系統消息為已讀時:" + (ex != null ? ex.Message : "")); } } } //Test //LogHelper.WriteLog("ThreadLoginCheckFunc()", "共向用戶:" + User.ID + "推送" + MsgsList.Rows.Count.ToString() + "條歷史命令."); } #endregion MsgsList.Dispose(); MsgsList = null; #endregion } catch (SocketException ex) { //test //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "向PC端" + DataTerminal + "推送未讀信息時出錯." + (ex != null ? ex.Message : "")); LogHelper.WriteLog("ThreadLoginCheckFunc()", "向PC端" + DataTerminal + "推送未讀信息和命令時出錯." + (ex != null ? ex.Message : "")); } //更新用戶狀態 try { DoUpdateUserLog(conn, UserID, "0", "0", "登錄"); DoUpdateUserState(conn, UserID, "1"); //上線中 } catch (Exception ex) { Passed = false; LogHelper.WriteLog("ThreadLoginCheckFunc()", "更新PC端用戶:" + DataTerminal + "狀態." + (ex != null ? ex.Message : "")); } conn.CloseConnection(); } if (Passed) { #region " 向移動端 客戶端推送平臺數據(在線人數等) - 暫不推送 " //try //{ // List<byte[]> MsgToPC = ConvertMethod.ConvertMsgToByte(string.Format(SysMessage, ActiveUsersCount, // OnlineUsersCount, // RegisteredUsersCount, // TodayMessagesCount, // TotalMessagesCount), // "9", "", "", "", "", ""); // //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 // lock (newClient) // { // foreach (byte[] msg in MsgToPC) // { // 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("ThreadLoginCheckFunc()", "向PC端" + DataTerminal + "推送平臺數據(在線人數等)." + (ex != null ? ex.Message : "")); //} #endregion } if (Passed) { // 將新連接加入轉發表並創建線程為其服務 lock (_mobile_transmit_tb.SyncRoot) { _mobile_transmit_tb.Add(UserID, MobileUser); } try { Thread clientThread = new Thread(new ParameterizedThreadStart(MobileThreadFunc)); //加入哈希表 _mobile_thread_tb.Add(UserID, clientThread); //clientThread.Start(userName); clientThread.Start(UserID); } catch (Exception ex) { try { // 發生錯誤時移除連接 lock (_mobile_transmit_tb.SyncRoot) { //_transmit_tb.Add(UserID, newClient); _mobile_transmit_tb.Remove(UserID); } } catch { } //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():開啟新線程", "建立登入用戶新線程時:" + ex.Message); LogHelper.WriteLog("ThreadLoginCheckFunc()", "建立登入用戶" + DataTerminal + "-" + DataTerminalName + "新線程時:" + (ex != null ? ex.Message : "")); } } } } #endregion break; case "FILE": #region " 文件傳送帳號登錄 " Passed = true; //try //{ // List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("登錄成功.", "2", UserID, DataTerminalName, DataGroup, Guid.NewGuid().ToString().Replace("-", "").ToUpper(), ""); // //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 // lock (newClient) // { // foreach (byte[] msg in msgs) // { // newClient.Send(msg); // } // } //} //catch (Exception ex) //{ // Passed = false; // //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():服務器開放登錄功能", "發送登陸成功信息時:" + ex.Message); // LogHelper.WriteLog("StartUp()", "發送登錄成功信息時" + (ex != null ? ex.Message : "")); //} if (Passed) { //創建連接對象 UserSocket AppUser = new UserSocket(); AppUser.ID = UserID; AppUser.Socket = newClient; AppUser.State = UserSocket.UserStates.Online; AppUser.Type = "F"; AppUser.SenderID = DataText.Split(new char[] { '|' })[0].Trim(); AppUser.ReceiverID = DataText.Split(new char[] { '|' })[1].Trim(); // 將新連接加入轉發表並創建線程為其服務 // Key-GUID永不重複 _file_transmit_tb.Add(UserID, AppUser); try { // 2016/02/22 // 接收者只能接收數據,不需要開啟Server-Reveived線程 if (UserID.Substring(UserID.Length - 1, 1) != "R") { Thread clientThread = new Thread(new ParameterizedThreadStart(FileThreadFunc)); //加入哈希表 _file_thread_tb.Add(UserID, clientThread); clientThread.Start(UserID); } else { //接收者已經登錄.找到S通道的發送者并向他發送允許建立T通道的通知. //發送者ID-接收者ID-GUID-R/S中第一個為對方的S通道帳號 //string SenderID = UserID.Substring(0, 50).Trim(); //string SenderGUID = UserID.Substring(51, 32).Trim(); string SenderGUID = UserID.Substring(0, UserID.Length - 2).Trim(); //缺異常處理.報錯后必須將接收者的T通道關閉 string MsgNO = ProcessTransferFileRequest("P", AppUser.SenderID, "P", AppUser.SenderID, "R", SenderGUID, "FILE", "RECEIVER"); if (MsgNO.Length == 0) { try { if (AppUser.Socket.Connected) { AppUser.Socket.Shutdown(SocketShutdown.Both); } AppUser.Socket.Close(); //LogHelper.WriteLog("StartUp()", "無效登錄請求被丟棄"); } catch { } try { //清除已加入的連接 _file_transmit_tb.Remove(UserID); } catch { } } } } catch (Exception ex) { try { //清除已加入的連接 _file_transmit_tb.Remove(UserID); } catch { } //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():開啟新線程", "建立登入用戶新線程時:" + ex.Message); LogHelper.WriteLog("StartUp()", "建立登入用戶" + DataTerminal + "-" + DataTerminalName + "新線程時:" + (ex != null ? ex.Message : "")); } } #endregion break; default: #region " PC端登錄 " UserSocket User = _transmit_tb[DataTerminal] as UserSocket; if (User != null) { Socket curSkt = User.Socket; #region " 發送離線 " try { List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("00", "7", DataTerminal, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper(), ""); //如果2秒內得不到之前登陸的對象,就直接干掉 //否則此帳號將永遠無法登錄 if (Monitor.TryEnter(curSkt, 2000)) { try { //向用戶本人發送離線 foreach (byte[] msg in msgs) { curSkt.Send(msg); //SendData(curSkt, msg); } } catch { } finally { Monitor.Exit(curSkt); } } else { //如果到這里說明之前登陸的對象已經死鎖 } //lock (curSkt) //{ // //向用戶本人發送離線 // foreach (byte[] msg in msgs) // { // curSkt.Send(msg); // } //} UpdateUserLog(UserID, "1", "0", "因相同帳號再次登陸而強制離線."); //log //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "相同帳號再次登陸:" + DataTerminal + " " + DataTerminalName); //LogHelper.WriteLog("StartUp()", "相同帳號再次登陸:" + DataTerminal + " " + DataTerminalName); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "轉發用戶" + UserID + "離線消息時:" + ex.Message); LogHelper.WriteLog("ThreadLoginCheckFunc()", "轉發用戶" + UserID + "離線消息時:" + (ex != null ? ex.Message : "")); } try { if (curSkt.Connected) { curSkt.Shutdown(SocketShutdown.Both); //curSkt.Disconnect(false); } curSkt.Close(); curSkt = null; Thread thread = _thread_tb[DataTerminal] as Thread; if (thread != null) { thread.Abort(); //線程池不會被遍歷,不鎖. _thread_tb.Remove(DataTerminal); } lock (_transmit_tb.SyncRoot) _transmit_tb.Remove(DataTerminal); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "嘗試關閉用戶" + DataTerminal + "線程和Socket連接時出錯." + (ex != null ? ex.Message : "")); LogHelper.WriteLog("ThreadLoginCheckFunc()", "嘗試關閉用戶" + DataTerminal + "線程和Socket連接時出錯." + (ex != null ? ex.Message : "")); } #endregion } // 驗證是否為唯一用戶 if (_transmit_tb.Count != 0 && _transmit_tb.ContainsKey(UserID)) { try { List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("登錄失敗.", "3", UserID, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper(), ""); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (newClient) { foreach (byte[] msg in msgs) { newClient.Send(msg); //SendData(newClient, msg); } } //test //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "PC端" + DataTerminal + "登錄失敗"); LogHelper.WriteLog("ThreadLoginCheckFunc()", "PC端" + DataTerminal + "登錄失敗"); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():驗證是否為唯一用戶", "發送登陸失敗信息時:" + ex.Message); LogHelper.WriteLog("ThreadLoginCheckFunc()", "發送登陸失敗信息時" + (ex != null ? ex.Message : "")); } } else { // 服務器開放登錄功能 try { List<byte[]> msgs = ConvertMethod.ConvertMsgToByte("登錄成功.", "2", UserID, DataTerminalName, DataGroup, Guid.NewGuid().ToString().Replace("-", "").ToUpper(), ""); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (newClient) { foreach (byte[] msg in msgs) { newClient.Send(msg); //SendData(newClient, msg); } } } catch (Exception ex) { Passed = false; //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():服務器開放登錄功能", "發送登陸成功信息時:" + ex.Message); LogHelper.WriteLog("ThreadLoginCheckFunc()", "發送登錄成功信息時" + (ex != null ? ex.Message : "")); } if (Passed) { //創建連接對象 User = new UserSocket(); User.ID = UserID; User.Socket = newClient; User.State = UserSocket.UserStates.Online; //登錄時群號規則: 普通用戶登錄時為空格, 外接應用(APP)登錄時為"APP" #region " 普通用戶才做以下操作 " if (DataGroup.Length == 0) { using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { #region " 獲得當前用記的所有聯絡人并向他們推送用戶上線消息 " StateNotifyQueue.Enqueue(new List<object>() { User, "1" }); //DataTable ContactsList = GetContacts(conn, UserID); //if (ContactsList.Rows.Count > 0) //{ // foreach (DataRow Contact in ContactsList.Rows) // { // //加入聯絡人(防呆自己加自己) // if (User.ID != Contact["contact_id"].ToString()) // User.Contacts.Add(Contact["contact_id"].ToString()); // } // //2016/02/27 // //For Test // //改為獨立線程來發,讓用戶登錄不受影響 // //如果此聯絡人在線就通知他(她)當前用戶上線了 // try // { // Thread stateThread = new Thread(new ParameterizedThreadStart(StateNotifyThreadFunc)); // stateThread.Start(User); // } // catch // { } // //SendUserState(User); //} //ContactsList.Dispose(); //ContactsList = null; #endregion //Test //LogHelper.WriteLog("ThreadLoginCheckFunc()", User.ID + "推送未讀消息."); #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()); // 判斷個人消息還是群消息 List<byte[]> rtnMsgs = ConvertMethod.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) { 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'"); //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("ThreadLoginCheckFunc()", "標識歷史信息為已讀時:" + (ex != null ? ex.Message : "")); } } } //Test LogHelper.WriteLog("ThreadLoginCheckFunc()", "共向用戶:" + User.ID + "推送" + MsgsList.Rows.Count.ToString() + "條歷史未讀消息."); } #endregion #region " 命令(取消推送) " //MsgsList = GetUnreadMsgs(conn, UserID, "C"); //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["cmd_no"].ToString())) // MaxMsgNO = long.Parse(UnreadMsg["cmd_no"].ToString()); // // 發給登錄人 // DateTime MsgDT = DateTime.Parse(UnreadMsg["cmd_date"].ToString() + " " + UnreadMsg["cmd_time"].ToString()); // // 判斷個人消息還是群消息 // List<byte[]> rtnMsgs = ConvertMethod.ConvertMsgToByte(UnreadMsg["cmd_text"].ToString(), // "C", // UnreadMsg["cmd_user"].ToString(), // UnreadMsg["user_name"].ToString(), // UnreadMsg["td_no"].ToString(), // MsgDT, // UnreadMsg["cmd_guid"].ToString(), // UnreadMsg["cmd_no"].ToString()); // //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 // lock (newClient) // { // foreach (byte[] msg in rtnMsgs) // { // newClient.Send(msg); // //SendData(newClient, msg); // } // } // } // // 更新為已讀 // try // { // MarkReadHistoryMsgQueue.Enqueue("update a set a.cmd_state='1' from lrcmdstate a where a.cmd_no<=" + MaxMsgNO.ToString() + " and a.cmd_to='" + UserID + "' and a.cmd_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("ThreadLoginCheckFunc()", "標識歷史命令為已讀時:" + (ex != null ? ex.Message : "")); // } // } // } // //Test // LogHelper.WriteLog("ThreadLoginCheckFunc()", "共向用戶:" + User.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 = ConvertMethod.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) { 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("ThreadLoginCheckFunc()", "標識歷史系統消息為已讀時:" + (ex != null ? ex.Message : "")); } } } //Test //LogHelper.WriteLog("ThreadLoginCheckFunc()", "共向用戶:" + User.ID + "推送" + MsgsList.Rows.Count.ToString() + "條歷史命令."); } #endregion MsgsList.Dispose(); MsgsList = null; #endregion } catch (SocketException ex) { //test //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "向PC端" + DataTerminal + "推送未讀信息時出錯." + (ex != null ? ex.Message : "")); LogHelper.WriteLog("ThreadLoginCheckFunc()", "向PC端" + DataTerminal + "推送未讀信息和命令時出錯." + (ex != null ? ex.Message : "")); } //更新用戶狀態 try { DoUpdateUserLog(conn, UserID, "0", "0", "登錄"); DoUpdateUserState(conn, UserID, "1"); //上線中 } catch (Exception ex) { Passed = false; LogHelper.WriteLog("ThreadLoginCheckFunc()", "更新PC端用戶:" + DataTerminal + "狀態." + (ex != null ? ex.Message : "")); } conn.CloseConnection(); } if (Passed) { #region " 向PC客戶端推送平臺數據(在線人數等) " try { List<byte[]> MsgToPC = ConvertMethod.ConvertMsgToByte(string.Format(SysMessage, ActiveUsersCount, OnlineUsersCount, RegisteredUsersCount, TodayMessagesCount, TotalMessagesCount), "9", "", "", "", "", ""); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (newClient) { foreach (byte[] msg in MsgToPC) { 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("ThreadLoginCheckFunc()", "向PC端" + DataTerminal + "推送平臺數據(在線人數等)." + (ex != null ? ex.Message : "")); } #endregion } } #endregion if (Passed) { // 將新連接加入轉發表並創建線程為其服務 lock (_transmit_tb.SyncRoot) { //_transmit_tb.Add(UserID, newClient); _transmit_tb.Add(UserID, User); } try { Thread clientThread = new Thread(new ParameterizedThreadStart(ThreadFunc)); //加入哈希表 _thread_tb.Add(UserID, clientThread); //clientThread.Start(userName); clientThread.Start(UserID); } catch (Exception ex) { try { // 發生錯誤時移除連接 lock (_transmit_tb.SyncRoot) { //_transmit_tb.Add(UserID, newClient); _transmit_tb.Remove(UserID); } } catch { } //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():開啟新線程", "建立登入用戶新線程時:" + ex.Message); LogHelper.WriteLog("ThreadLoginCheckFunc()", "建立登入用戶" + DataTerminal + "-" + DataTerminalName + "新線程時:" + (ex != null ? ex.Message : "")); } } } } #endregion break; } } else if (DataType == "WS" && DataTerminal.Length > 0) { //LogHelper.WriteLog("StartUp()", "手機端用戶: " + DataTerminal + "-" + DataTerminalName + " 請求登錄"); #region " Web端登錄 " UserID = DataTerminal; // 用戶帳號 bool Passed = true; //Socket curSkt = _ws_transmit_tb[DataTerminal] as Socket; UserSocket User = _ws_transmit_tb[DataTerminal] as UserSocket; if (User != null) { Socket curSkt = User.Socket; #region " 發送離線 " try { byte[] msg = WebConvertMethod.ConvertMsgToByte("00", "7", DataTerminal, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper()); //如果2秒內得不到之前登陸的對象,就直接干掉 //否則此帳號將永遠無法登錄 if (Monitor.TryEnter(curSkt, 2000)) { try { //向用戶本人發送離線 curSkt.Send(msg); //SendData(curSkt, msg); } catch { } finally { Monitor.Exit(curSkt); } } else { //如果到這里說明之前登陸的對象已經死鎖 } //curSkt.Send(msg); UpdateUserLog(UserID, "0", "1", "因相同帳號再次登錄而強制離線."); //clsClientLog.WriteLog(clsClientLog.LogType.Error, "WebThreadFunc(object obj):default", "相同帳號異地登陸:" + DataTerminal + " " + DataTerminalName); //LogHelper.WriteLog("StartUp()", "手機端相同帳號重複登陸:" + DataTerminal + "-" + DataTerminalName); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "WebThreadFunc(object obj):default", "轉發發送離線消息時:" + ex.Message); //LogHelper.WriteLog("StartUp()", "轉發發送離線消息時" + (ex != null ? ex.Message : "")); LogHelper.WriteLog("StartUp()", "轉發手機用戶" + UserID + "離線消息時:" + (ex != null ? ex.Message : "")); } try { if (curSkt.Connected) { curSkt.Shutdown(SocketShutdown.Both); //curSkt.Disconnect(false); } curSkt.Close(); curSkt = null; Thread thread = _ws_thread_tb[DataTerminal] as Thread; if (thread != null) { thread.Abort(); //線程池不會被遍歷,不鎖. _ws_thread_tb.Remove(DataTerminal); } lock (_ws_transmit_tb.SyncRoot) _ws_transmit_tb.Remove(DataTerminal); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "嘗試關閉用戶" + DataTerminal + "線程和Socket連接時出錯." + (ex != null ? ex.Message : "")); LogHelper.WriteLog("StartUp()", "嘗試關閉手機用戶" + DataTerminal + "線程和Socket連接時出錯." + (ex != null ? ex.Message : "")); } #endregion } // 驗證是否為唯一用戶 if (_ws_transmit_tb.Count != 0 && _ws_transmit_tb.ContainsKey(UserID)) { try { byte[] msg = WebConvertMethod.ConvertMsgToByte("登錄失敗.", "3", UserID, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper()); lock (newClient) { newClient.Send(msg); //SendData(newClient, msg); } LogHelper.WriteLog("StartUp()", "手機端" + DataTerminal + "登錄失敗"); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():驗證是否為唯一用戶", "發送登陸失敗信息時:" + ex.Message); LogHelper.WriteLog("StartUp()", "發送登陸失敗信息時" + (ex != null ? ex.Message : "")); } } else { // 服務器開放登錄功能 try { byte[] msg = WebConvertMethod.ConvertMsgToByte("登錄成功.", "2", UserID, DataTerminalName, "", Guid.NewGuid().ToString().Replace("-", "").ToUpper()); //鎖住線程,保證本次發送完成後其他線程才能對此用戶發送消息 lock (newClient) { newClient.Send(msg); //SendData(newClient, msg); } } catch (Exception ex) { Passed = false; //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():服務器開放登錄功能", "發送登陸成功信息時:" + ex.Message); LogHelper.WriteLog("StartUp()", "發送登錄成功信息時" + (ex != null ? ex.Message : "")); } if (Passed) { //創建連接對象 User = new UserSocket(); User.ID = UserID; User.Socket = newClient; User.State = UserSocket.UserStates.Online; using (SQLHelper conn = new SQLHelper(DBInfo)) { conn.OpenConnection(); try { #region " 獲得當前用記的所有聯絡人并向他們推送用戶上線消息 " StateNotifyQueue.Enqueue(new List<object>() { User, "1" }); //DataTable ContactsList = GetContacts(conn, UserID); //if (ContactsList.Rows.Count > 0) //{ // foreach (DataRow Contact in ContactsList.Rows) // { // //加入聯絡人(防呆自己加自己) // if (User.ID != Contact["contact_id"].ToString()) // User.Contacts.Add(Contact["contact_id"].ToString()); // } // //改為獨立線程來發 // //如果此聯絡人在線就通知他(她)當前用戶上線了 // //try // //{ // // Thread stateThread = new Thread(new ParameterizedThreadStart(StateNotifyThreadFunc)); // // stateThread.Start(User); // //} // //catch // //{ } // //如果此聯絡人在線就通知他(她)當前用戶上線了 // SendUserState(User); //} //ContactsList.Dispose(); //ContactsList = null; #endregion #region " 發送所有未讀訊息(手機版暫時不推未讀取消息) " //DataTable MsgsList = GetUnreadMsgs(conn, UserID); //if (MsgsList.Rows.Count > 0) //{ // if (newClient != null) // { // foreach (DataRow UnreadMsg in MsgsList.Rows) // { // // 發給登錄人 // DateTime MsgDT = DateTime.Parse(UnreadMsg["msg_date"].ToString() + " " + UnreadMsg["msg_time"].ToString()); // byte[] rtnMsg = WebConvertMethod.ConvertMsgToByte(UnreadMsg["msg_text"].ToString(), // UnreadMsg["td_no"].ToString().Length > 0 ? "4" : "U", // UnreadMsg["msg_from"].ToString(), // UnreadMsg["user_name"].ToString(), // UnreadMsg["td_no"].ToString(), // MsgDT, // UnreadMsg["msg_guid"].ToString()); // lock (newClient) // { // newClient.Send(rtnMsg); // } // } // // 更新為已讀 // conn.ExecuteSQL("update a set a.msg_state='1' from lrmsgstate a where a.msg_to='" + UserID + "' and a.msg_state='0'"); // } //} //MsgsList.Dispose(); //MsgsList = null; #endregion } catch (SocketException ex) { //test //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp()", "向PC端" + DataTerminal + "推送未讀信息時出錯." + (ex != null ? ex.Message : "")); LogHelper.WriteLog("StartUp()", "向Mobile端" + DataTerminal + "推送未讀信息時出錯." + (ex != null ? ex.Message : "")); } try { //更新用戶狀態 DoUpdateUserLog(conn, UserID, "0", "1", "登錄"); DoUpdateUserState(conn, UserID, "1"); //上線中 } catch (Exception ex) { Passed = false; LogHelper.WriteLog("StartUp()", "更新Mobile端用戶:" + DataTerminal + "狀態." + (ex != null ? ex.Message : "")); } conn.CloseConnection(); } if (Passed) { // 將新連接加入轉發表並創建線程為其服務 lock (_ws_transmit_tb.SyncRoot) { //_ws_transmit_tb.Add(UserID, newClient); _ws_transmit_tb.Add(UserID, User); } //LogHelper.WriteLog("StartUp()", "手機端" + DataTerminal + "已添加到在線用戶列表"); try { Thread clientThread = new Thread(new ParameterizedThreadStart(WebThreadFunc)); //加入哈希表 _ws_thread_tb.Add(UserID, clientThread); //clientThread.Start(userName); clientThread.Start(UserID); //LogHelper.WriteLog("StartUp()", "手機端" + DataTerminal + "-" + DataTerminalName + "登錄成功"); } catch (Exception ex) { try { // 發生錯誤時移除連接 lock (_ws_transmit_tb.SyncRoot) { //_transmit_tb.Add(UserID, newClient); _ws_transmit_tb.Remove(UserID); } } catch { } //clsClientLog.WriteLog(clsClientLog.LogType.Error, "StartUp():開啟新線程", "建立登入用戶新線程時:" + ex.Message); LogHelper.WriteLog("StartUp()", "建立登入用戶" + DataTerminal + "-" + DataTerminalName + "新線程時:" + (ex != null ? ex.Message : "")); } } } } //需不需要干掉自己? //Thread.CurrentThread.Abort(); #endregion } else { // 無效訊息-丟棄 try { if (newClient.Connected) { newClient.Shutdown(SocketShutdown.Both); //clientSkt.Disconnect(false); } newClient.Close(); //LogHelper.WriteLog("StartUp()", "無效登錄請求被丟棄"); } catch (SocketException ex) { //clsClientLog.WriteLog(clsClientLog.LogType.System, "CloseClientSocket", "嘗試關閉一個異常的Socket連接時出現問題:" + ex.Message); LogHelper.WriteLog("ThreadLoginCheckFunc", "嘗試關閉一個無法識別的Socket連接請求時出現問題:" + (ex != null ? ex.Message : "")); } } } catch (Exception ex) { LogHelper.WriteLog("ThreadLoginCheckFunc", "用戶登錄時發生錯誤:" + (ex != null ? ex.Message : "")); } finally { // 2016/02/27 // 回收到隊列 LoginThreadsQueue.Enqueue(LoginThread); //LogHelper.WriteLog("ThreadLoginCheckFunc", "回收登錄線程[" + LoginThread.ManagedThreadId.ToString() + "]"); } } ////需不需要干掉自己? //try //{ // Thread.CurrentThread.Abort(); //} //catch //{ } }