/// <summary> /// 指定された時間以前の過去ログを取得する /// </summary> /// <param name="data"></param> /// <param name="cookies"></param> /// <param name="userId"></param> /// <param name="when">取得開始時間</param> /// <param name="resFrom"></param> /// <returns></returns> internal static Chat[] ReceiveLog(IMessageServerStatus data, System.Net.CookieContainer cookies, int userId, DateTime when, int resFrom) { List<Chat> results = new List<Chat>(1000); TcpClient tcpClient = null; try { Waybackkey key = Waybackkey.GetInstance(data.Thread, cookies); if (key != null) { bool timeouted = false; using (System.Threading.ManualResetEvent m = new System.Threading.ManualResetEvent(false)) { tcpClient = new TcpClient(); tcpClient.SendTimeout = 1000; tcpClient.ReceiveTimeout = 1000; AsyncCallback ac = (AsyncCallback)delegate(IAsyncResult ar) { if (!timeouted) { m.Set(); TcpClient tcp = (TcpClient)ar.AsyncState; tcp.EndConnect(ar); } }; tcpClient.BeginConnect(data.Address, data.Port, ac, tcpClient); // 既定時間以内に接続できない場合は失敗とする if (!m.WaitOne(ApiSettings.Default.DefaultConnectionTimeout, false)) { timeouted = true; throw new Exception("過去ログ取得:コネクションタイムアウト"); } } // NetworkStreamは自動的に開放されないのでusingで囲む using (NetworkStream ns = tcpClient.GetStream()) { string msg = String.Format(ApiSettings.Default.WaybackThreadStartMessageFormat, data.Thread, resFrom, Utility.DateTimeToUnixTime(when), key.Value, userId); byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(msg + '\0'); ns.Write(sendBytes, 0, sendBytes.Length); byte[] buffer = new byte[ApiSettings.Default.ReceiveBufferSize]; int last = 0; //DataAvailableはすべて取得しきる前にfalseを返してしまうので使えない while (ns.CanRead) { int b = ns.ReadByte(); if (b == -1) { break; } int i; for (i = 0; b != (int)'\0' && b != -1 && i < buffer.Length; i++, b = ns.ReadByte()) { buffer[i] = (byte)b; } string block = System.Text.Encoding.UTF8.GetString(buffer, 0, i); if (block.StartsWith("<chat")) { Chat chat = null; try { chat = new Chat(block); } catch (Exception ex) { chat = null; Logger.Default.LogErrorMessage(ex.Message); } if (chat != null) { results.Add(chat); // 指定数読み込んだ場合は終了 if (chat.No == last) { break; } } } else if (block.StartsWith("<thread")) { ThreadHeader th = new ThreadHeader(block); last = th.LastRes; // コメントがない状態ではエラーが発生するのでBreakする if (last == 0) { break; } } } } } } catch (System.IO.IOException) { } catch (Exception ex) { Logger.Default.LogException(ex); } finally { if (tcpClient != null) { tcpClient.Close(); } } return results.ToArray(); }
/// <summary> /// メッセージサーバーに接続したことを通知します。 /// </summary> /// <param name="threadHeader"></param> protected override void OnConnectServer(ThreadHeader threadHeader) { lock (_lastResSync) { _lastRes = threadHeader.LastRes; } base.OnConnectServer(threadHeader); }
/// <summary> /// メッセージサーバーに接続したことを通知します。 /// </summary> /// <param name="threadHeader"></param> protected virtual void OnConnectServer(ThreadHeader threadHeader) { if (this.ConnectServer != null) { if (_asyncOperation != null) { _asyncOperation.Post(postConnectServerEvent, new ConnectServerEventArgs(threadHeader)); } else { postConnectServerEvent(new ConnectServerEventArgs(threadHeader)); } } }
/// <summary> /// コメントを受信した際に発生するイベントの引数 /// </summary> /// <param name="threadHeader"></param> internal ConnectServerEventArgs(ThreadHeader threadHeader) { _th = threadHeader; }
/// <summary> /// サーバーから受け取ったXMLデータを解析する /// オーバーライドする際は基底を呼び出さないとOnConnectServerイベントが発生しなくなる /// </summary> /// <param name="node"></param> protected virtual void ParseReceivedData(System.Xml.XmlNode node) { if (node.FirstChild.Name.Equals("thread")) { // スレッドデータであった場合(接続直後に送られてくる) _threadHeader = new ThreadHeader(node); this.OnConnectServer(_threadHeader); } }